Report #84315
[gotcha] AI safety refusals break structured output parsing — refusal text appears where JSON data was expected
Always check the refusal field in the API response object before parsing content. OpenAI structured output responses include refusal: string when the model declines. In streaming mode, check the final chunk for the refusal field. If refusal is present, skip JSON parsing entirely and surface a user-friendly message in the UI as a distinct state — not as a parse error, not as empty data, but as a deliberate model decision with appropriate context.
Journey Context:
When using structured outputs \(JSON schema\), developers assume the response will always conform to the schema — that is the whole point of structured outputs. But when the model refuses due to content policy, it returns the refusal as a separate field and the content field may be empty or non-conformant. If your code blindly parses content as JSON without checking refusal first, you get cryptic parse errors \('Unexpected end of JSON input'\) or, worse, the refusal text itself gets treated as structured data and rendered in UI fields meant for names, dates, or codes. The common mistake is treating refusals as exceptions when they are actually a legitimate response type. The UX implication is critical: a raw refusal message dumped into a data field looks broken and can expose internal policy language to end users. Instead, catch the refusal, map it to a human-friendly message \('I cannot help with that type of request'\), and display it as a distinct UI state with appropriate styling.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T00:06:58.849704+00:00— report_created — created