{"record":{"id":"395db54f076daa63","repo":"can1357/oh-my-pi","slug":"devin-api-error-response-body-is-empty","errorCode":null,"errorMessage":"Devin API error: response body is empty","messagePattern":"Devin API error: response body is empty","errorType":"exception","errorClass":"AIError.ProviderResponseError","httpStatus":null,"severity":"error","filePath":"packages/ai/src/providers/devin.ts","lineNumber":220,"sourceCode":"\t\t\t\t\t\"connect-content-encoding\": \"gzip\",\n\t\t\t\t\t\"accept-encoding\": \"identity\",\n\t\t\t\t\t\"user-agent\": \"connect-go/1.18.1 (go1.26.3)\",\n\t\t\t\t\t\"connect-accept-encoding\": \"gzip\",\n\t\t\t\t\t...(options?.headers ?? {}),\n\t\t\t\t},\n\t\t\t\tbody: frame,\n\t\t\t\tsignal: options?.signal,\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst text = await response.text();\n\t\t\t\tthrow new AIError.DevinApiError(\n\t\t\t\t\t`Devin API error ${response.status} ${response.statusText}: ${text}`,\n\t\t\t\t\tresponse.status,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!response.body) {\n\t\t\t\tthrow new AIError.ProviderResponseError(\"Devin API error: response body is empty\", {\n\t\t\t\t\tprovider: model.provider,\n\t\t\t\t\tkind: \"empty-body\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst body = response.body;\n\n\t\t\tstream.push({ type: \"start\", partial: output });\n\n\t\t\tconst reader = body.getReader();\n\t\t\tlet pending = Buffer.alloc(0);\n\n\t\t\tfor (;;) {\n\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\tif (value && value.length > 0) {\n\t\t\t\t\t// Steady state drains fully per chunk; view the fresh reader chunk\n\t\t\t\t\t// instead of copying it through Buffer.concat (see aws-eventstream.ts).\n\t\t\t\t\tpending =\n\t\t\t\t\t\tpending.length === 0","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/ai/src/providers/devin.ts#L202-L238","documentation":"After a successful (2xx) HTTP response, streamDevin expects a readable response body to consume the event stream. If response.body is null/undefined it throws ProviderResponseError with kind \"empty-body\", since a status-only response carries no stream data the provider can parse.","triggerScenarios":"Devin API returns 2xx but the fetch implementation provides no body — degenerate server response, an intermediary stripping the body, or a transport/polyfill that nulls bodies on certain statuses or configurations.","commonSituations":"Corporate proxies or gateways swallowing response bodies; custom fetch implementations that mishandle streaming responses; Devin server-side anomaly returning an empty 200.","solutions":["Retry the request — likely a transient server-side anomaly.","Ensure the fetch implementation passed to the provider supports streaming response bodies (no body-nulling polyfills).","Check intermediaries (proxies, gateways) for body-stripping behavior on streaming responses.","If persistent, capture status/headers and report to Devin support; it indicates a server-side empty response."],"exampleFix":"null","handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"try {\n  await streamDevin(model, ctx, options);\n} catch (err) {\n  if (err instanceof AIError.ProviderResponseError && err.kind === \"empty-body\") {\n    // transient empty 2xx: retry with backoff\n    await Bun.sleep(retryDelayMs);\n    return streamDevin(model, ctx, options);\n  }\n  throw err;\n}","preventionTips":["Use a fetch implementation with full streaming body support.","Retry idempotent Devin requests on empty-body responses.","Audit proxies/gateways for response-body stripping on streams."],"tags":["network","empty-response","devin","streaming"],"backgroundTag":"empty-response-body","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}