{"record":{"id":"e810053d51b961c9","repo":"koala73/worldmonitor","slug":"body-too-large","errorCode":"body-too-large","errorMessage":"Request body exceeds ${maxBytes} bytes","messagePattern":"Request body exceeds (.+?) bytes","errorType":"http","errorClass":"RequestBodyTooLargeError","httpStatus":413,"severity":"error","filePath":"api/mcp/bounded-body.ts","lineNumber":80,"sourceCode":" * oversized bodies are cancelled rather than buffered to completion, and the\n * unread tail is never copied into the returned buffer.\n */\nexport async function readBoundedRequestBody(\n  request: Request,\n  maxBytes: number,\n): Promise<Uint8Array> {\n  if (!Number.isFinite(maxBytes) || maxBytes < 0) {\n    throw new TypeError('maxBytes must be a non-negative finite number');\n  }\n\n  const contentLengthRaw = request.headers.get('content-length');\n  if (contentLengthRaw !== null && contentLengthRaw !== '') {\n    const contentLength = Number(contentLengthRaw);\n    if (Number.isFinite(contentLength) && contentLength > maxBytes) {\n      if (request.body) {\n        await request.body.cancel().catch(() => {});\n      }\n      throw new RequestBodyTooLargeError(maxBytes);\n    }\n  }\n\n  if (!request.body) return new Uint8Array();\n\n  const reader = request.body.getReader();\n  const chunks: Uint8Array[] = [];\n  let total = 0;\n  try {\n    while (true) {\n      const { done, value } = await reader.read();\n      if (done) break;\n      if (!value || value.byteLength === 0) continue;\n      total += value.byteLength;\n      if (total > maxBytes) {\n        await reader.cancel().catch(() => {});\n        throw new RequestBodyTooLargeError(maxBytes);\n      }","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/koala73/worldmonitor/blob/9361220cc013571781071f0206e4d80fd14b2f7f/api/mcp/bounded-body.ts#L62-L98","documentation":"readBoundedRequestBody() enforces a byte cap on incoming MCP/A2A request bodies. Before streaming the body it checks the Content-Length header, and if it declares more than maxBytes it cancels the stream early and throws RequestBodyTooLargeError (code 'body-too-large') without buffering any bytes. This is the fast-fail path for oversized payloads.","triggerScenarios":"A client sends an HTTP request with a Content-Length header greater than the configured maxBytes to an endpoint using readBoundedRequestBody (e.g. api/mcp-proxy.ts, api/a2a.ts, api/docs-mcp.ts).","commonSituations":"An agent uploading a very large JSON-RPC params blob; a misbehaving client that doesn't chunk; a proxy forwarding an unbounded upstream body; integrations posting file attachments to a tool-call endpoint.","solutions":["Shrink the client-side payload below maxBytes before sending (trim params, paginate large arrays).","If the payload is legitimately large, raise the endpoint's configured maxBytes bound to an appropriate value and redeploy.","If a proxy is inflating requests, fix the proxy to forward compact bodies and correct Content-Length.","Confirm the client is not double-encoding (e.g. base64-in-JSON) which multiplies body size."],"exampleFix":"// before\nawait fetch('/api/mcp', { method: 'POST', body: JSON.stringify(hugeParams) });\n// after\nconst body = JSON.stringify(hugeParams);\nif (new Blob([body]).size > MAX_BYTES) throw new Error('payload too large');\nawait fetch('/api/mcp', { method: 'POST', body, headers: { 'content-length': String(body.length) } });","handlingStrategy":"validation","validationCode":"const bytes = new TextEncoder().encode(JSON.stringify(params)).length;\nconst MAX_BYTES = 1 << 20; // match endpoint config\nif (bytes > MAX_BYTES) throw new Error(`payload ${bytes}B exceeds ${MAX_BYTES}B limit`);","typeGuard":"null","tryCatchPattern":"try {\n  const body = await readBoundedRequestBody(request, { maxBytes });\n} catch (err) {\n  if (err instanceof RequestBodyTooLargeError) {\n    return new Response(JSON.stringify({ error: 'body-too-large', maxBytes: err.maxBytes }), { status: 413 });\n  }\n  throw err;\n}","preventionTips":["Check Content-Length client-side before sending large payloads.","Keep MCP tool params small; paginate or summarize large datasets.","Mirror the server's maxBytes in client config so limits stay in sync.","For big data, use a bulk/upload endpoint instead of the bounded JSON-RPC body."],"tags":["http","request-body","limits","mcp"],"backgroundTag":"request-body-too-large","analyzedSha":"9361220cc013571781071f0206e4d80fd14b2f7f","analyzedAt":"2026-09-01T10:32:37.851Z","contentChangedAt":"2026-09-01T10:32:37.851Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}