AIERROR故障诊断台
排障指南 / GUIDE

OpenAI Structured Outputs返回400或解析失败:JSON Schema排查指南

核验更新:2026-08-29证据状态:VERIFIED

直接答案

OpenAI Structured Outputs返回400或解析失败:JSON Schema排查指南

症状、差异与判断依据

Structured Outputs和普通JSON模式有什么区别:普通 JSON mode 主要保证输出是合法 JSON,不保证字段、枚举和嵌套结构符合你的业务定义。Structured Outputs 通过 jsonschema 和 strict 约束输出,使结果遵循所提供的受支持 Schema。若业务依赖固定字段,不应只在提示词里写“请严格输出 JSON”,而应使用适用模型和端点支持的结构化输出配置。

第一步

保存完整错误而不是只记录400:HTTP 400 只是错误类别,真正有用的是响应体中的错误消息、参数路径、错误类型,以及响应头里的请求标识。日志应保存端点、模型、SDK 版本、Schema 哈希和脱敏后的错误对象,不要记录 API Key 或用户敏感输入。若代理只向应用返回“上游失败”,先绕过代理复现,确认 OpenAI 原始错误没有被覆盖。

确认Responses API参数层级

在 Responses API 中,结构化文本格式放在 text.format 下;不要机械复制 Chat Completions 的 responseformat 结构。配置层级写错时,请求可能提示未知参数或类型不匹配。先使用官方文档当前示例构造最小请求,再逐项加入业务 Schema、工具和其他参数。不要同时保留旧字段和新字段“碰运气”。 模型可用性和支持能力应以当前官方模型文档及账户实际返回为准,不要把某个示例模型名称硬编码成永久事实。

所有字段为什么都要放进required

OpenAI 官方 Structured Outputs 指南说明,所有字段或函数参数都必须列入 required。如果 properties 定义了三个字段,却只把两个加入 required,严格 Schema 会被拒绝。这里的“required”表示输出对象必须包含这个键,不代表业务值一定非空。

可选字段用null联合类型表达

如果字段在业务上允许缺失,结构化输出中可把它设为可空类型,同时仍把字段名放入 required。这样输出始终具有稳定键集合,未知值明确为 null,而不是时有时无。 客户端类型也要接受 null。如果 SDK 生成的模型把字段声明成非空字符串,API 即使返回合规 JSON,客户端仍可能在反序列化时失败。

additionalProperties必须逐层检查

严格对象通常需要明确 additionalProperties: false,以禁止 Schema 外字段。最容易遗漏的是数组 items 内的对象、$defs 中的复用对象和多层嵌套对象。只在根对象设置一次并不会自动约束所有子对象。按每一个 type: object 节点检查 properties、required 和 additionalProperties 是否成套存在。

不是完整JSON Schema都受支持

Structured Outputs 支持 JSON Schema 的一个子集,而不是任意验证器能接受的全部关键字。一个 Schema 在本地 Draft 2020-12 验证器中合法,不代表 API 的严格输出功能一定支持。遇到 400 时,先把 Schema 缩减为对象、字符串、数值、布尔、数组、枚举和简单联合,再逐项加回约束,定位具体不支持或组合方式错误的关键字。

Schema名称也要符合约束

格式名称不是随意标题。应使用简短、稳定、只含允许字符的名称,避免空格、中文标点和超长动态字符串。不要把用户输入直接拼进 Schema 名称。若名称用于缓存或日志,单独保存业务版本号,不要每个请求都生成全新 Schema 名称。

区分文本结构化输出和函数调用

如果模型应该返回供用户界面展示的固定 JSON,使用 Structured Outputs 的文本格式;如果模型应该选择并调用应用函数,则在 function tool 的 parameters 中定义 Schema,并按函数调用流程回传结果。两者的配置位置、响应项目和后续处理不同。把函数参数 Schema 放进 text.format,或把最终答案 Schema 当函数工具,都会增加不必要的分支。

strict应该放在正确层级

文本格式的 strict 属于 JSON Schema 格式配置;函数调用的严格模式属于函数工具定义。将 strict 写进业务 schema 对象内部,或放在请求根部,可能被判未知字段。调试时打印最终发送的 JSON,而不是只看代码中的 Pydantic、Zod 或类型定义,因为 SDK 转换后的结构才是 API 实际收到的内容。

SDK模型与原始Schema不一致怎么办

SDK 辅助函数会把 Pydantic、Zod 或其他类型模型转换为 Schema。升级 SDK 后,默认生成方式可能变化;自定义验证器、转换器或某些复杂联合类型也未必能映射到受支持子集。将 SDK 生成的最终 Schema 输出到测试日志,与一个可工作的原始 JSON Schema 做结构化差异比较。不要通过字符串顺序判断差异。

排障步骤与验证

请求成功不代表一定有parsed结果

应用不能假定每次成功响应都包含可解析的结构化文本。应先检查响应整体状态,再遍历正确的输出项目,区分文本、拒答和其他项目。若只读取固定数组下标,加入工具或响应结构变化后就可能拿错项目。使用官方 SDK 的解析辅助能力时,也要处理 parsed 为空的分支。

必须单独处理refusal

OpenAI 官方文档指出,安全原因造成的拒答不一定遵循你提供的 Schema,响应会用拒答内容标识该情况。应用应把 refusal 作为显式业务分支:向用户展示合适说明、记录安全事件类型,并停止把拒答文本传入普通 JSON 解析器。不能把 refusal 当成“模型破坏 Schema”后无限重试。

incomplete与输出Token不足

Responses API 可能返回 incomplete,并在详情里说明原因,例如达到最大输出 Token。结构化 JSON 若在生成末尾被截断,应用不应尝试用补括号等方式伪造成功。检查 status 和 incompletedetails,适当增加输出预算、缩短 Schema 或输入,并根据业务幂等性决定是否重试。

内容过滤中断也不是Schema错误

生成可能因内容过滤中断,结果自然无法形成完整结构。此时应按响应状态与详情处理,而不是把错误归因于 required 或 additionalProperties。监控系统至少区分:请求 400、refusal、incomplete/max output tokens、content filter、SDK parse error 和应用后置校验失败。

不要盲目重试HTTP 400

Schema 无效、参数层级错误或模型不支持通常是确定性请求问题。对完全相同的 400 请求指数退避不会成功,只会增加成本和噪声。错误分类后,应让配置进入失败队列并告警;只有网络错误、限流或服务端临时错误才按照对应策略重试。修复 Schema 后用新的配置版本重新提交。

用最小Schema二分定位

先用只有一个必填字符串字段的根对象验证模型、端点和参数层级。成功后按嵌套对象、数组、枚举、可空字段、$defs 的顺序逐组加回。每次变更记录 Schema 哈希。若某一组加入后出现 400,就在该组继续二分,通常比阅读数百行生成 Schema 更快。

建立Schema预检和版本控制

把 Schema 当代码管理:固定名称、业务版本、生成器版本和哈希;在 CI 中检查每个对象的字段是否全部 required、是否关闭额外属性、是否包含禁用关键字,以及示例实例是否通过本地业务校验。预检不能完全替代 API 支持验证,但能在发布前拦截大部分结构错误。

生产验收应覆盖哪些样本

至少测试正常完整输入、缺失可选值、空数组、枚举边界、深层嵌套、长文本、可能拒答的安全样本和低输出预算样本。分别断言完成状态、refusal 分支、incomplete 分支、解析类型和业务校验。不要只用一个“天气示例”证明真实业务 Schema 可用。

日志与隐私边界

记录响应请求 ID、HTTP 状态、错误码、模型、SDK 版本、Schema 名称和哈希即可定位大多数问题。用户原文和完整模型输出可能包含敏感数据,应按数据治理要求脱敏或不落盘。API Key 绝不能写入错误报告、截图或前端日志。

总结

Structured Outputs 故障要按三层定位:请求层检查端点、参数位置和受支持 Schema;生成层区分 completed、refusal 与 incomplete;客户端层检查输出项目、SDK 解析和业务校验。把所有字段列为 required、用 null 表达可选值、逐层关闭额外属性,并通过最小 Schema、版本化预检和多分支验收,可以避免把确定性的 400 当成随机模型问题。

常见问题

JSON在本地验证通过为什么API仍返回400?

本地验证器可能支持完整 JSON Schema,而 Structured Outputs 只支持其中一个子集;也可能是所有字段未列入 required、嵌套对象缺少 `additionalProperties: false`,或参数层级写错。

可选字段是不是不能使用?

可以使用可空联合类型表达业务可选值,同时仍把字段键列入 required。这样输出结构稳定,缺失含义由 `null` 表示。

strict为true后还需要业务校验吗?

需要。Schema 保证结构,不保证内容在业务上真实、权限允许或跨字段逻辑一定成立。金额、ID、时间范围和资源归属仍需应用校验。

为什么响应成功却没有parsed?

可能是 refusal、incomplete、内容过滤、读取了错误输出项目,或 SDK 与响应格式配置不匹配。先按响应状态和内容类型分支,再读取解析对象。

400错误应该自动重试吗?

同一无效 Schema 或参数的 400 通常不应自动重试。应先修正请求;对限流、网络或服务端临时错误使用各自的受控重试策略。

官方与规范资料

OpenAI API 错误处理OpenAI 官方文档

Responses API:Create a model responseOpenAI 官方文档