{"record":{"id":"b617d0ed632475e0","repo":"Hmbown/CodeWhale","slug":"payload-too-large","errorCode":null,"errorMessage":"payload too large","messagePattern":"payload too large","errorType":"http","errorClass":"BodyReadError","httpStatus":413,"severity":"error","filePath":"web/lib/bounded-body.ts","lineNumber":29,"sourceCode":"    try { await request.body?.cancel(message); } catch { /* Keep the original rejection. */ }\n    throw new BodyReadError(status, message);\n  };\n  const rawLength = request.headers.get(\"content-length\");\n  if (rawLength !== null) {\n    if (!/^\\d+$/.test(rawLength)) return reject(400, \"invalid Content-Length\");\n    if (Number(rawLength) > maxBytes) return reject(413, \"payload too large\");\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      total += value.byteLength;\n      if (total > maxBytes) throw new BodyReadError(413, \"payload too large\");\n      chunks.push(value);\n    }\n  } catch (cause) {\n    try { await reader.cancel(\"body rejected\"); } catch { /* Preserve the read/size error. */ }\n    throw cause instanceof BodyReadError ? cause : new BodyReadError(400, \"body read failed\");\n  } finally {\n    reader.releaseLock();\n  }\n  const bytes = new Uint8Array(total);\n  let offset = 0;\n  for (const chunk of chunks) {\n    bytes.set(chunk, offset);\n    offset += chunk.byteLength;\n  }\n  return bytes;\n}\n","sourceCodeStart":11,"sourceCodeEnd":46,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/web/lib/bounded-body.ts#L11-L46","documentation":"readBoundedBody streams the request body and accumulates a byte count. When the total exceeds maxBytes it throws BodyReadError(413) immediately, so oversized payloads are cut off without buffering the whole body.","triggerScenarios":"Any request whose streaming body bytes exceed the maxBytes limit passed to readBoundedBody — typically a login/admin form POST larger than the configured cap, even if Content-Length was absent or lying.","commonSituations":"Uploading a large body to a route meant for small form posts; a client with chunked encoding bypassing the Content-Length early check; a maxBytes configured smaller than the legitimate payload size after a config change.","solutions":["Reduce the request body size below the route's maxBytes limit.","Increase the maxBytes argument at the call site if the route legitimately needs larger bodies.","Ensure the client sends the payload to the correct endpoint (large uploads belong on an upload route, not the bounded form route)."],"exampleFix":"// before\nconst body = await readBoundedBody(request, 4 * 1024);\n// after\nconst body = await readBoundedBody(request, 16 * 1024);","handlingStrategy":"validation","validationCode":"// Client-side precheck before sending\nif (new TextEncoder().encode(body).byteLength > MAX_BYTES) {\n  throw new Error(`body exceeds ${MAX_BYTES} byte limit`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  const body = await readBoundedBody(request, MAX);\n} catch (err) {\n  if (err instanceof BodyReadError && err.status === 413) {\n    return new Response(\"payload too large\", { status: 413 });\n  }\n  throw err;\n}","preventionTips":["Know each route's maxBytes cap and size-check payloads client-side before POSTing.","Send large uploads to dedicated endpoints instead of bounded form routes.","Document the body limit in the route and surface it to clients in error handling."],"tags":["http","payload-size","validation"],"backgroundTag":"payload-too-large","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}