{"record":{"id":"0eeba6a0e7158be6","repo":"different-ai/openwork","slug":"agent-diagnostics-request-too-large","errorCode":"agent_diagnostics_request_too_large","errorMessage":"Agent diagnostics request body is too large","messagePattern":"Agent diagnostics request body is too large","errorType":"http","errorClass":"ApiError","httpStatus":413,"severity":"error","filePath":"apps/server/src/server.ts","lineNumber":3759,"sourceCode":"  const tooLarge = () => new ApiError(\n    413,\n    \"agent_diagnostics_request_too_large\",\n    \"Agent diagnostics request body is too large\",\n  );\n  const timedOut = () => new ApiError(\n    408,\n    \"agent_diagnostics_request_timeout\",\n    \"Agent diagnostics request body timed out\",\n  );\n  const configuredDeadlineMs = Number(process.env.OPENWORK_AGENT_DIAGNOSTICS_BODY_TIMEOUT_MS);\n  const deadlineMs = Number.isFinite(configuredDeadlineMs) && configuredDeadlineMs >= 50\n    ? Math.min(configuredDeadlineMs, 10_000)\n    : AGENT_DIAGNOSTICS_DEFAULT_BODY_DEADLINE_MS;\n  const declaredLength = request.headers.get(\"content-length\");\n  if (declaredLength !== null) {\n    const declaredBytes = Number(declaredLength);\n    if (Number.isFinite(declaredBytes) && declaredBytes > AGENT_DIAGNOSTICS_MAX_REQUEST_BYTES) {\n      throw tooLarge();\n    }\n  }\n\n  const reader = request.body?.getReader();\n  if (!reader) {\n    throw new ApiError(400, \"invalid_json\", \"Invalid JSON body\");\n  }\n  const chunks: Uint8Array[] = [];\n  let size = 0;\n  let deadlineExpired = false;\n  let activeRead: ReturnType<typeof reader.read> | undefined;\n  let deadlineTimer: ReturnType<typeof setTimeout> | undefined;\n  const deadline = new Promise<never>((_resolve, reject) => {\n    deadlineTimer = setTimeout(() => {\n      deadlineExpired = true;\n      reject(timedOut());\n    }, deadlineMs);\n  });","sourceCodeStart":3741,"sourceCodeEnd":3777,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/server/src/server.ts#L3741-L3777","documentation":"The agent diagnostics endpoint enforces AGENT_DIAGNOSTICS_MAX_REQUEST_BYTES and rejects early via the Content-Length header before reading the stream. If the declared body size exceeds the cap, `tooLarge()` throws ApiError with code `agent_diagnostics_request_too_large` without consuming the body. This guards memory and prevents oversized diagnostic payloads from being processed at all.","triggerScenarios":"Client POSTs (or PUTs) to the agent diagnostics endpoint with a Content-Length header whose numeric value exceeds AGENT_DIAGNOSTICS_MAX_REQUEST_BYTES.","commonSituations":"Diagnostics collector accidentally embedding full session transcripts or base64 screenshots; batch tooling uploading aggregated diagnostics in one request; misconfigured client chunking that sends everything in a single call.","solutions":["Shrink the client payload: trim diagnostic fields, drop transcripts/screenshots, or raise the server limit if legitimately needed","Split the diagnostics into multiple requests each under AGENT_DIAGNOSTICS_MAX_REQUEST_BYTES","Send with Transfer-Encoding: chunked only if the streamed size is actually under the cap — the streaming reader enforces the same limit","Compress the payload (gzip) and decompress server-side if the endpoint supports it"],"exampleFix":"// before\nfetch(url, { method: \"POST\", body: JSON.stringify(allDiagnostics) }) // Content-Length > cap\n// after\nconst body = JSON.stringify(essentialDiagnostics);\nif (new Blob([body]).size <= AGENT_DIAGNOSTICS_MAX_REQUEST_BYTES) {\n  fetch(url, { method: \"POST\", body });\n} else {\n  await uploadInChunks(essentialDiagnostics);\n}","handlingStrategy":"validation","validationCode":"const bytes = new Blob([JSON.stringify(diagnostics)]).size;\nif (bytes > AGENT_DIAGNOSTICS_MAX_REQUEST_BYTES) {\n  throw new Error(`payload ${bytes}B exceeds limit ${AGENT_DIAGNOSTICS_MAX_REQUEST_BYTES}B`);\n}","typeGuard":"null","tryCatchPattern":"try {\n  await submitDiagnostics(diagnostics);\n} catch (e) {\n  if (e instanceof ApiError && e.code === \"agent_diagnostics_request_too_large\") {\n    await submitDiagnostics(truncateDiagnostics(diagnostics));\n  } else throw e;\n}","preventionTips":["Measure serialized payload size client-side before POST","Send Content-Length accurately so the header check matches reality","Truncate transcripts/screenshots in diagnostics collection","Chunk large diagnostic uploads"],"tags":["http","validation","request-size","diagnostics"],"backgroundTag":"request-body-too-large","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}