everything/tasks: tasks/update checks MAX_ANSWER_BYTES against string length, so non-ASCII answers exceed the documented byte budget
Los mantenedores suelen responder en 1 día
Evaluación
- Dificultad
- 1/5
- Tiempo estimado
- Menos de una hora
- Aptitud para principiantes
- 78/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- typescript
- Área
- backend
Línea de trabajo
La comprobación de tamaño está en el manejador tasks/update de src/everything/server/tasks.ts, alrededor de las líneas 411-424, donde JSON.stringify(answered).length se compara con MAX_ANSWER_BYTES. Lee ese bloque y luego reproduce el problema enviando una respuesta de 33.000 caracteres é y confirmando que se acepta. Está terminado cuando la medición cuenta bytes UTF-8, de modo que esa carga recibe un error -32602 y la tarea queda sin cambios.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
| Field | Value |
|---|---|
| Labels (suggested) | bug, everything, tasks |
| Reproduced on | commit 163a5e935756 (default branch at the time of analysis) |
| Introduced by | commit 27b2d2415cdc0ad13782edb8b6c3cecd7846b78a — "feat(everything): serve both protocol eras and demonstrate …" |
Summary
The everything server's tasks/update handler limits the size of client-supplied answers with
MAX_ANSWER_BYTES, but computes the size with JSON.stringify(answered).length. In JavaScript that is
the number of UTF-16 code units, not bytes. For any non-ASCII answer the guard under-counts by up to
3× and lets a payload that is larger than the documented byte budget through, after which the oversized
answers are handed to task.behavior.receive() and retained in the task.
Affected code
src/everything/server/tasks.ts, lines 411–424 at 163a5e935756:
const answered = Object.fromEntries(
Object.entries(inputResponses).filter(([key]) =>
outstanding.includes(key),
),
);
const size = JSON.stringify(answered).length; // <- UTF-16 code units, not bytes
if (size > MAX_ANSWER_BYTES) {
throw new ProtocolError(
ProtocolErrorCode.InvalidParams,
`Invalid params for tasks/update: the answers are ${size} bytes, over the ${MAX_ANSWER_BYTES}-byte limit; the task is unchanged`,
);
}
if (Object.keys(answered).length > 0) {
task.behavior.receive(answered, now);
}
The constant is named MAX_ANSWER_BYTES and the error message promises a byte comparison
("the answers are N bytes"), so the unit mismatch is internal to the handler, not a documentation
question.
Expected behavior
tasks/update rejects the request with -32602 Invalid params because the serialized answers are
66 012 bytes, which is over the 65 536-byte budget; the task is left unchanged.
Actual behavior
Calling tasks/update with one outstanding answer whose text is 33 000 é characters, the handler accepts the payload and retains it in the task (MAX_ANSWER_BYTES = 65536).
Payload: one outstanding answer whose text is 33 000 U+00E9 (é) characters.
MAX_ANSWER_BYTES = 65536.
{"mode":"bug","outcome":{"accepted":true,"received":66012}}
TASKS_UPDATE_BYTE_BUDGET_BYPASSED
JSON.stringify(...).length= 33 012 → passes the guard.- UTF-8
Buffer.byteLength(..., "utf8")= 66 012 → 476 bytes over the limit. - The task retained the answer (
received: 66012), so the documented limit was not enforced.
Control: the same probe against a copy of tasks.ts with line 416 changed to
Buffer.byteLength(JSON.stringify(answered), "utf8") produces
{"mode":"control","outcome":{"accepted":false,
"error":"-32602: Invalid params for tasks/update: the answers are 66012 bytes, over the 65536-byte limit; the task is unchanged"}}
CONTROL_REJECTED_BY_BYTES
and retained is undefined — the divergence disappears with that one line.
Why it matters
- The limit is a resource guard for retained task state (the answer is stored until the task settles).
Non-ASCII answers — ordinary for any non-English client, or for base64/emoji content — get up to a 3×
larger effective budget. 33 000 characters of CJK/Cyrillic/emoji-style text becomes ~99 KB against a
stated 64 KiB ceiling. - The rejection message itself reports a byte count that is not a byte count, which makes the failure
mode confusing for client authors.
Suggested fix
Use a byte-accurate measure:
const size = Buffer.byteLength(JSON.stringify(answered), "utf8");
(new TextEncoder().encode(...).length if the file must stay runtime-agnostic). Note that both forms
count the UTF-8 serialization of the JSON text, which is what the limit documents.
- Lenguaje dominante
- TypeScript
- Estrellas
- 91.7k
- Forks
- 11.9k
- Merge medio
- 3 h 30 min
- PR fusionados (30 d)
- 204
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de modelcontextprotocol/servers
-
fix(docker): correct stale --db-path comments in fetch/git Dockerfiles and clarify git READMEAbiertobug v2
Dificultad 1/5 Menos de una hora Aptitud para principiantes 88/100
modelcontextprotocol/servers#5483 ·
Los mantenedores suelen responder en 1 día
-
bug v2
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
modelcontextprotocol/servers#5482 ·
Los mantenedores suelen responder en 1 día
-
chore dependencies server-filesystem v2
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
modelcontextprotocol/servers#5481 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
CI: rename everything-mcp-diff.yml to mcp-interface-diff.yml, staged across a milestone mergeAbiertochore v2
Dificultad 4/5 3-5 días Aptitud para principiantes 45/100
modelcontextprotocol/servers#5463 ·
Los mantenedores suelen responder en 1 día
-
bug server-filesystem v2
Dificultad 5/5 Más de una semana Aptitud para principiantes 25/100
modelcontextprotocol/servers#5260 · 3 comentarios ·
Los mantenedores suelen responder en 1 día
Todos los issues de modelcontextprotocol/servers
Issues similares
-
Chip source filter and denial markers miss Storage rows when a Storage activity source is pickedAbiertobug
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 77/100
omdsh-dev/DSH-better-sidebar#1141 ·
Los mantenedores suelen responder en 2 días
-
desktop linux photos
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
Los mantenedores suelen responder en 1 día
-
Cleanup SetupPosiblemente ocupada @AlexanderKaran la tomó hoy. Abiertodocumentation enhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 64/100
e18e/framework-tracker#769 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
Los mantenedores suelen responder en 1 día