{"record":{"id":"a6c1da4ce1e4f7b6","repo":"paperclipai/paperclip","slug":"empty-agentmail-response","errorCode":null,"errorMessage":"Empty AgentMail response","messagePattern":"Empty AgentMail response","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/src/services/agentmail-api.ts","lineNumber":189,"sourceCode":"        Authorization: `Bearer ${apiKey}`,\n        \"Content-Type\": \"application/json\",\n        ...(idempotencyKey ? { \"Idempotency-Key\": idempotencyKey } : {}),\n      },\n      body: body === undefined ? undefined : JSON.stringify(body),\n    });\n    if (!response.ok) {\n      const retryAfter = response.headers.get(\"retry-after\");\n      const seconds = Number(retryAfter ?? 1);\n      const delay = Number.isFinite(seconds)\n        ? seconds * 1000\n        : Date.parse(retryAfter ?? \"\") - Date.now();\n      throw new AgentmailApiError(\n        response.status,\n        Math.max(1000, Math.min(300_000, Number.isFinite(delay) ? delay : 1000)),\n      );\n    }\n    if (response.status === 204) return undefined as T;\n    if (!response.body) throw new Error(\"Empty AgentMail response\");\n    const reader = response.body.getReader();\n    const parts: Uint8Array[] = [];\n    let bytes = 0;\n    try {\n      for (;;) {\n        const part = await reader.read();\n        if (part.done) break;\n        bytes += part.value.length;\n        if (bytes > 16 * 1024 * 1024)\n          throw new Error(\"AgentMail response exceeds the processing limit\");\n        parts.push(part.value);\n      }\n    } finally {\n      await reader.cancel();\n    }\n    return JSON.parse(Buffer.concat(parts).toString(\"utf8\")) as T;\n  }\n  const inboxPath = (id: string) => `/inboxes/${encodeURIComponent(id)}`;","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/agentmail-api.ts#L171-L207","documentation":"The AgentMail API client's request method streams the response body, and it throws this error when the HTTP response is not a 204 but has no body at all (response.body is null/undefined). Since a non-204 AgentMail response is expected to carry a JSON payload, an empty body indicates a truncated or malformed response from the upstream AgentMail service, and parsing cannot proceed.","triggerScenarios":"AgentMail returns a non-204 status with a null/empty body — e.g. a proxy or load balancer swallowing the body, an early connection close after headers, or a misbehaving AgentMail endpoint responding 200 with zero bytes.","commonSituations":"Reverse proxies (nginx/ALB) terminating the upstream connection mid-response; AgentMail service incident producing header-only responses; aggressive timeouts at an intermediary that drop the body but keep the status line.","solutions":["Retry the request — this is usually a transient upstream/proxy issue; the client may already back off on some statuses, but an empty-body 200 warrants a manual retry.","Check AgentMail service status and any intermediary proxy logs for truncated responses.","Reduce intermediary buffering/timeouts that could terminate the body stream early.","If persistent, capture the response status/headers and report the issue to the AgentMail provider."],"exampleFix":"// before\nconst data = await agentmailApi(client).request(\"GET\", \"/v1/threads\");\n// after\nlet data;\nfor (let attempt = 0; attempt < 3; attempt++) {\n  try { data = await agentmailApi(client).request(\"GET\", \"/v1/threads\"); break; }\n  catch (e) {\n    if (e.message === \"Empty AgentMail response\" && attempt < 2) continue;\n    throw e;\n  }\n}","handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"try { return await api.request(method, path); }\ncatch (e) {\n  if (e.message === \"Empty AgentMail response\") return withBackoffRetry(() => api.request(method, path));\n  throw e;\n}","preventionTips":["Retry transient empty-body responses with backoff","Check proxy/ALB logs for truncated upstream responses","Monitor AgentMail status during incidents","Keep intermediary timeouts generous enough for full body transfer"],"tags":["agentmail","network","empty-response"],"backgroundTag":"empty-response-body","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}