{"record":{"id":"2a4bd343a8aad207","repo":"koala73/worldmonitor","slug":"payload-too-large","errorCode":null,"errorMessage":"payload_too_large","messagePattern":"payload_too_large","errorType":"exception","errorClass":"Error","httpStatus":413,"severity":"error","filePath":"api/security/report.js","lineNumber":68,"sourceCode":"    effectivePolicy: shortString(body.effectivePolicy, 120),\n    blockedURLOrigin: safeOrigin(body.blockedURL),\n    destination: shortString(body.destination, 80),\n  };\n}\n\nfunction summarizeReports(payload) {\n  const reports = Array.isArray(payload) ? payload : [payload];\n  return {\n    count: reports.length,\n    truncated: reports.length > MAX_REPORT_ITEMS,\n    reports: reports.slice(0, MAX_REPORT_ITEMS).map(summarizeReportItem),\n  };\n}\n\nasync function readBodyWithLimit(req) {\n  const contentLength = Number(req.headers.get('content-length') ?? 0);\n  if (Number.isFinite(contentLength) && contentLength > MAX_REPORT_BYTES) {\n    throw new Error('payload_too_large');\n  }\n\n  if (!req.body) return '';\n\n  const reader = req.body.getReader();\n  const chunks = [];\n  let total = 0;\n\n  while (true) {\n    const { value, done } = await reader.read();\n    if (done) break;\n\n    total += value.byteLength;\n    if (total > MAX_REPORT_BYTES) {\n      await reader.cancel();\n      throw new Error('payload_too_large');\n    }\n    chunks.push(value);","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/koala73/worldmonitor/blob/ffec79ac339946fd2d24e85845da5755dcaa534b/api/security/report.js#L50-L86","documentation":"Thrown by readBodyWithLimit() in the security report edge function when the Content-Length request header is present, finite, and exceeds MAX_REPORT_BYTES (32 KB / 32768 bytes). This is the fast-path rejection — the body is never read, saving edge function execution time and memory. The function is used to protect the CSP/COEP/CORP violation-reporting endpoint from oversized payloads.","triggerScenarios":"POSTing to /api/security/report with a Content-Length header greater than 32768 bytes. This could be a single very large report or an array of reports whose total serialized size exceeds 32 KB. The check uses the header value before any body reading, so even a streaming body is never consumed.","commonSituations":"A browser sending a large violation report batch (many CSP violations in one POST); a malicious or buggy client sending an oversized payload; a reporting client that does not batch-limit its reports; a misconfigured report endpoint collecting too many violations before flushing.","solutions":["Reduce the report payload to under 32 KB — send fewer reports per POST, or split a large batch into multiple requests (MAX_REPORT_ITEMS is 20).","If the report is a single oversized item, trim or summarize it client-side before sending.","If legitimate traffic routinely exceeds 32 KB, consider raising MAX_REPORT_BYTES (but weigh edge function memory/execution limits).","Clients should set a batch flush timer or count limit so they never accumulate >32 KB before POSTing."],"exampleFix":"// before — client sends 500 reports in one POST (>32KB)\nfetch('/api/security/report', { method: 'POST', body: JSON.stringify(allReports) })\n// after — batch into chunks of 20\nfor (let i = 0; i < allReports.length; i += 20) {\n  await fetch('/api/security/report', { method: 'POST', body: JSON.stringify(allReports.slice(i, i + 20)) });\n}","handlingStrategy":"validation","validationCode":"// Validate payload size before POSTing to the report endpoint\nconst MAX_REPORT_BYTES = 32 * 1024; // 32 KB — mirror the server limit\nconst MAX_REPORT_ITEMS = 20;\nfunction batchReports(reports) {\n  return reports.slice(0, MAX_REPORT_ITEMS).map(r => JSON.stringify(r)).join('');\n}\nconst serialized = batchReports(myReports);\nif (new Blob([serialized]).size > MAX_REPORT_BYTES) {\n  // Split into smaller batches\n  const chunks = chunkArray(myReports, 10); // halve the batch\n  for (const chunk of chunks) {\n    await postReport(chunk);\n  }\n} else {\n  await postReport(myReports);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set a Content-Length header on report POSTs so the server can fast-reject oversized payloads.","Batch reports to at most 20 items per POST (MAX_REPORT_ITEMS).","Monitor client-side payload size and split before sending if approaching 32 KB."],"tags":["security","payload-limit","edge-function","report-endpoint"],"backgroundTag":null,"analyzedSha":"ffec79ac339946fd2d24e85845da5755dcaa534b","analyzedAt":"2026-08-12T11:24:56.012Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}