Report #42133
[gotcha] AI content refusals return as HTTP 200 with a refusal field, silently bypassing error handling and rendering as broken UI
Check for the \`refusal\` field in the chat completion response object separately from HTTP status code handling. Render refusals as a distinct UI state—not as an error, not as a normal response—with contextual guidance on how to rephrase the request.
Journey Context:
When OpenAI's API refuses a request due to content policy, it returns HTTP 200 with a \`refusal\` field in the response object and empty or apologetic content. This is deeply counter-intuitive: most developers expect refusals to be 4xx errors. If you only handle errors via HTTP status codes, refusals pass through your error handling entirely and you display 'I'm sorry, but I can't assist with that' as if it's the intended output. If you try to detect refusals by parsing response text for apology patterns, you'll get false positives \(the model sometimes apologizes legitimately\) and false negatives \(refusals don't always contain 'sorry'\). The correct pattern is to check the \`refusal\` field explicitly—it's a first-class field in the response object. In the UI, render a distinct 'refused' state that explains what happened and suggests how to rephrase, rather than showing the raw refusal text which looks broken and unhelpful in a product context.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T01:11:30.424158+00:00— report_created — created