fix(mcp): commentId-тулы молча падают на обрезанном UUID — нужна внятная ошибка «id must be a full UUID» #436

Closed
opened 2026-07-10 05:05:27 +03:00 by agent_vscode · 1 comment
Collaborator

Симптом (реальный кейс из прода)

Ночью 2026-07-10 (чат 019f4983-0d60-70a4-976c-8dd62f5802c1, run 2) модель передала в resolve_comment обрезанный UUID — префикс реального id:

{"resolved": true, "commentId": "019f499a-9f8c"}
{"resolved": true, "commentId": "019f499c-6e36"}

Полные id (019f499a-9f8c-7d68-b7be-ce100d7c6c56, …) модель до этого сама получала из результатов create_comment / list_comments, но при пересказе укоротила их до первых двух групп.

Что происходит сейчас

  1. DocmostClient.resolveComment() (packages/mcp/src/client.ts, ~2724) никак не валидирует commentId и сразу POST-ит в /comments/resolve.
  2. Сервер режет запрос на DTO-валидации: ResolveCommentDto имеет @IsUUID() → 400.
  3. В MCP-клиенте нет интерцептора, извлекающего тело ответа, поэтому до модели долетает голый AxiosError: «Request failed with status code 400» — без намёка, что не так и как исправить.
  4. До деплоя #407 было ещё хуже: throw вообще не персистился, и в реплее следующего хода вызов выглядел как Tool call did not complete. — модель ретраила вслепую (вклад в петлю из #(флуд комментариев)).

Модель из такой ошибки не может понять, что надо всего лишь взять полный id из list_comments.

Затронутые тулы

Все, кто принимает commentId и прокидывает его в REST как есть:

  • resolve_comment (resolveComment)
  • update_comment (updateComment)
  • delete_comment (deleteComment)
  • create_comment c parentCommentId (reply)

Предлагаемый фикс

Fail-fast валидация формата UUID на стороне MCP-клиента (до POST), с actionable-текстом ошибки, например:

resolve_comment: 'commentId' must be the FULL comment UUID (36 chars,
e.g. 019f499a-9f8c-7d68-b7be-ce100d7c6c56), got '019f499a-9f8c'.
Copy the id verbatim from list_comments / create_comment output.
  • одна общая хелпер-функция assertFullUuid(toolName, paramName, value) в client.ts, применить во всех четырёх местах;
  • (опционально, отдельным шагом) generic-извлечение error.response.data.message для остальных 4xx, чтобы серверные валидационные ошибки доходили до модели читаемым текстом, а не «status code 400».

Критерии приёмки

  • Обрезанный/невалидный commentId в любом из четырёх тулов возвращает модели ошибку с текстом «full comment UUID» и примером, без сетевого запроса.
  • Юнит-тесты: валидный UUID проходит, префикс/мусор — падает с ожидаемым сообщением (для всех четырёх тулов).
  • Поведение с валидным UUID не меняется.

Контекст

Найдено при разборе инцидента «агенты в петле» 2026-07-10 (флуд дублей комментариев на странице про прошивку ESP; связанные фиксы: #407 персист tool-error, #427 подсказки якоря, #431 CollabSession).

## Симптом (реальный кейс из прода) Ночью 2026-07-10 (чат `019f4983-0d60-70a4-976c-8dd62f5802c1`, run 2) модель передала в `resolve_comment` **обрезанный UUID** — префикс реального id: ```json {"resolved": true, "commentId": "019f499a-9f8c"} {"resolved": true, "commentId": "019f499c-6e36"} ``` Полные id (`019f499a-9f8c-7d68-b7be-ce100d7c6c56`, …) модель до этого сама получала из результатов `create_comment` / `list_comments`, но при пересказе укоротила их до первых двух групп. ## Что происходит сейчас 1. `DocmostClient.resolveComment()` (`packages/mcp/src/client.ts`, ~2724) никак не валидирует `commentId` и сразу POST-ит в `/comments/resolve`. 2. Сервер режет запрос на DTO-валидации: `ResolveCommentDto` имеет `@IsUUID()` → 400. 3. В MCP-клиенте нет интерцептора, извлекающего тело ответа, поэтому до модели долетает голый AxiosError: **«Request failed with status code 400»** — без намёка, что не так и как исправить. 4. До деплоя #407 было ещё хуже: throw вообще не персистился, и в реплее следующего хода вызов выглядел как `Tool call did not complete.` — модель ретраила вслепую (вклад в петлю из #(флуд комментариев)). Модель из такой ошибки не может понять, что надо всего лишь взять полный id из `list_comments`. ## Затронутые тулы Все, кто принимает `commentId` и прокидывает его в REST как есть: - `resolve_comment` (`resolveComment`) - `update_comment` (`updateComment`) - `delete_comment` (`deleteComment`) - `create_comment` c `parentCommentId` (reply) ## Предлагаемый фикс Fail-fast валидация формата UUID на стороне MCP-клиента (до POST), с actionable-текстом ошибки, например: ``` resolve_comment: 'commentId' must be the FULL comment UUID (36 chars, e.g. 019f499a-9f8c-7d68-b7be-ce100d7c6c56), got '019f499a-9f8c'. Copy the id verbatim from list_comments / create_comment output. ``` - одна общая хелпер-функция `assertFullUuid(toolName, paramName, value)` в client.ts, применить во всех четырёх местах; - (опционально, отдельным шагом) generic-извлечение `error.response.data.message` для остальных 4xx, чтобы серверные валидационные ошибки доходили до модели читаемым текстом, а не «status code 400». ## Критерии приёмки - Обрезанный/невалидный `commentId` в любом из четырёх тулов возвращает модели ошибку с текстом «full comment UUID» и примером, без сетевого запроса. - Юнит-тесты: валидный UUID проходит, префикс/мусор — падает с ожидаемым сообщением (для всех четырёх тулов). - Поведение с валидным UUID не меняется. ## Контекст Найдено при разборе инцидента «агенты в петле» 2026-07-10 (флуд дублей комментариев на странице про прошивку ESP; связанные фиксы: #407 персист tool-error, #427 подсказки якоря, #431 CollabSession).
Author
Collaborator

Объединено в #437 (фаза B полной спеки диагностики ошибок тулов). Закрываю как дубликат/поглощённое.

Объединено в #437 (фаза B полной спеки диагностики ошибок тулов). Закрываю как дубликат/поглощённое.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: vvzvlad/gitmost#436