{"record":{"id":"0f238e55cc05a445","repo":"HeyPuter/puter","slug":"bad-response","errorCode":"bad_response","errorMessage":"an empty response was generated","messagePattern":"an empty response was generated","errorType":"http","errorClass":"HttpError","httpStatus":400,"severity":"error","filePath":"src/backend/drivers/ai-chat/utils/OpenAIUtil.js","lineNumber":557,"sourceCode":"        .map((item) => ({\n            id: item.call_id,\n            type: 'function',\n            function: {\n                name: item.name,\n                arguments: item.arguments,\n            },\n            ...(item.id ? { canonical_id: item.id } : {}),\n        }));\n\n    // Inline-compaction artifact, if the upstream compacted this turn.\n    const compactionItem = output.find((item) => item?.type === 'compaction');\n\n    const is_empty = completion.output_text.trim() === '';\n    if (is_empty && responseToolCalls.length < 1 && !compactionItem) {\n        // GPT refuses to generate an empty response if you ask it to,\n        // so this will probably only happen on an error condition.\n        // A compaction-only output is legitimate, so don't reject it.\n        throw new HttpError(400, 'an empty response was generated', {\n            legacyCode: 'bad_response',\n        });\n    }\n\n    // We need to moderate the completion too\n    const mod_text = completion.output_text;\n    if (moderate && mod_text !== null) {\n        const moderation_result = await moderate(mod_text);\n        if (moderation_result.flagged) {\n            throw new HttpError(400, 'message is not allowed', {\n                legacyCode: 'bad_request',\n            });\n        }\n    }\n\n    const ret = {\n        finish_reason: 'stop',\n        index: 0,","sourceCodeStart":539,"sourceCodeEnd":575,"githubUrl":"https://github.com/HeyPuter/puter/blob/908ec23eda38526170322c3edf71ba45ecb1ca95/src/backend/drivers/ai-chat/utils/OpenAIUtil.js#L539-L575","documentation":"Thrown by the Responses-API output handler (handle_completion_output_responses_api) when completion.output_text is empty after trimming AND there are no function_call tool calls AND no compaction artifact in the output. The comment notes GPT normally won't produce an empty response on demand, so this is treated as an upstream error condition rather than valid output.","triggerScenarios":"A Responses-API chat call returns a completion whose output_text is whitespace-only/empty, with no tool_calls and no inline compaction item — e.g. upstream model error, truncated response, or a degenerate request the model couldn't answer.","commonSituations":"Upstream provider hiccup, model overloaded/refused mid-generation, malformed message history that yields nothing, or an edge case where the model emits only reasoning and no visible output.","solutions":["Retry the request once — empty responses are usually transient upstream errors.","Simplify or fix the message history being sent (remove malformed/empty user turns).","If reproducible, capture the raw completion to see whether the model returned reasoning-only or errored, then adjust the request.","Catch HTTP 400 'an empty response was generated' and fall back to a different model."],"exampleFix":"// before\nconst r = await puter.ai.chat(messages, { model: 'gpt-5-response' });\n// after — retry once on empty\nlet r;\ntry { r = await puter.ai.chat(messages, { model: 'gpt-5-response' }); }\ncatch (e) {\n  if (e.code === 'bad_response' && /empty response/.test(e.message)) {\n    r = await puter.ai.chat(messages, { model: 'gpt-5-response' }); // one retry\n  } else throw e;\n}","handlingStrategy":"retry","validationCode":"// Validate message history before sending — drop empty/whitespace user turns.\nconst clean = messages.filter(m => !(m.role === 'user' && String(m.content ?? '').trim() === ''));\nif (clean.length === 0) throw new Error('no non-empty messages');","typeGuard":null,"tryCatchPattern":"let resp;\ntry {\n  resp = await puter.ai.chat(messages, { stream: false });\n} catch (e) {\n  if (e?.code === 'bad_response' && /empty response/i.test(e?.message)) {\n    resp = await puter.ai.chat(messages, { stream: false }); // single retry\n  } else throw e;\n}","preventionTips":["Sanitize message history (no empty turns) before the call.","Retry once — empty Responses-API output is usually a transient upstream error.","Fall back to a different model if the error is reproducible."],"tags":["ai-chat","responses-api","empty-response","bad-response"],"backgroundTag":null,"analyzedSha":"908ec23eda38526170322c3edf71ba45ecb1ca95","analyzedAt":"2026-08-12T20:53:15.911Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}