CModel 错误模型
CModel Error Contract 1.0.0 的三字段响应结构、HTTP 语义和调用规则。
CModel Error Contract 1.0.0 用于百积木拥有的非流式 HTTP 和 Module 调用边界。公共响应只包含 contractVersion、errorCode 和 data 三个字段;服务不能再输出 value、systemCurrentTime、error 或 { success, message }、{ code, message } 等私有响应。
公共机器可读源事实与 SDK:
- CModel 响应 JSON Schema
- npm:
npm install @baijimu/cmodel
每个公开 API 必须在自身文档中登记调用方能够观察和处理的稳定 errorCode。平台内部可以保留错误目录、分类、诊断信息和类型,但这些内部字段不能序列化进公共响应,也不能改变 CModel 固定的 HTTP 200。
适用边界
本契约适用于百积木拥有的非流式 HTTP API 和 Module 方法响应。
以下边界保留各自的协议 envelope,并由最外层 Adapter 与 CModel 做一次确定性转换:
- 健康检查和就绪探针;
- SSE、WebSocket 等已经发出响应头的流式协议;
- MCP、OpenAI、Anthropic 和第三方供应商协议;
- 浏览器重定向、文件下载等非 JSON 响应。
外部错误格式不能继续进入百积木内部业务链路。
成功响应
{
"contractVersion": "1.0.0",
"errorCode": "0",
"data": {
"id": "example"
}
}成功响应必须同时满足:
- HTTP 状态为
200; contractVersion缺省时按1.0.0解析;显式提供时必须为严格 SemVer1.0.0;errorCode为字符串"0";data由具体 API 或 Runtime 方法的返回类型定义。
使用 CModel envelope 的接口不能返回 204 No Content。
失败响应
{
"contractVersion": "1.0.0",
"errorCode": "PAYMENT_REQUIRED",
"data": {
"message": "当前账户余额不足,请充值后重试",
"retryable": false
}
}失败响应必须同时满足:
- HTTP 状态为
200; errorCode是非"0"的稳定字符串错误码;data可以为null,或包含必填message与retryable的标准公开错误详情对象;message是 1 到 512 个字符、可直接展示给用户的安全文案;retryable表示在不改变输入、授权或账户状态时,原操作能否通过重试成功。
业务失败必须使用 HTTP 200。HTTP 只表示 CModel envelope 已被正常传输,业务成败只由 errorCode 表达:"0" 为成功,非 "0" 为失败。网关、代理或容器在 CModel Handler 之外产生的非 200 响应属于传输或基础设施失败,不得伪装成 CModel 业务响应。
Envelope 与业务数据边界
CModel envelope 解析器只读取并校验三个已知字段:
contractVersionerrorCodedata
解析器必须忽略其他顶层字段。旧响应中残留的 value、systemCurrentTime、error 及其子字段都按未知顶层字段处理,不能导致协议解析失败,也不能继续作为业务判断或用户展示来源。为兼容协议版本字段引入前的 1.0.0 响应,消费者在 contractVersion 缺失时必须补成 1.0.0;一旦字段存在,非法 SemVer 或非 1.0.0 版本仍是协议错误。新生产者只能输出三个标准字段,并显式输出 contractVersion。
成功响应 data 的内部结构不由 CModel envelope 校验,具体 API、Module 方法或 Runtime methodDefinition 负责定义和校验。失败响应 data 由 CModel 统一定义为 null 或标准公开错误详情;消费者必须校验 message 和 retryable,并原样保留对象中的未知属性,以允许具体 API 在 1.0.0 中追加已文档化的公开操作信息。未知属性不能用于错误分类;分类仍只依赖该 API 登记的稳定 errorCode。
错误身份与公开边界
平台内部错误目录可以继续保存错误所有者、原因、分类、重试语义、用户文案和诊断索引,但公共调用方只依赖当前 API 文档登记的:
errorCode- 该 API 对此错误的稳定说明
data.message,仅用于用户展示data.retryable,仅用于决定是否自动重试
最外层 Adapter 负责把内部错误确定性映射成 errorCode,只把已经审查为可公开展示的用户文案和稳定重试语义写入失败 data,并把有效 CModel envelope 统一输出为 HTTP 200。原始上游错误消息、数据库错误、堆栈、Token、Secret、内部域名、完整请求体和个人数据不能进入公共响应。
HTTP 消费规则
调用方收到有效 CModel envelope 后,必须解析 envelope 并以 errorCode 判断业务结果:
- HTTP
200可以承载成功或业务失败;errorCode == "0"为成功,非"0"为失败。 - 失败响应的
data可以是null或标准{ message, retryable }对象;null兼容已有生产者。 contractVersion缺失时按1.0.0处理;显式值非法或不受支持时报告协议错误,不做版本协商。- 不接受数字
0、error_code、顶层code/message或缺失errorCode。 - 忽略所有未知顶层字段;成功
data交给具体接口的类型解析器,失败data交给 CModel 标准错误详情解析器。标准解析器校验message、retryable并保留端点扩展字段,但不得用扩展字段猜测错误类别。 - 错误分类只使用
errorCode和当前 API 文档;不得用 HTTP 状态、value、data.message或上游自然语言文本分类。
为支持已上线服务滚动迁移,SDK 1.1.4 的消费者可以解析历史非 200 失败 envelope,但仍只依据非零 errorCode 返回业务失败;所有新生产者和已迁移生产者必须输出 HTTP 200。当生产者盘点确认不再存在历史响应后,删除这项有明确退出条件的 consumer 兼容行为。
流式错误
流式协议不使用 CModel envelope。负责该流的协议必须定义自己的版本化错误事件,并在进入百积木非流式业务边界时由所属 Adapter 完成一次确定性转换。
不得把流内失败当作普通文本、成功数据或 JSON 解析异常吞掉。
收敛要求
生产者、消费者和 Gateway 必须直接收敛到同一个 1.0.0 三字段模型:
- 消费者只解析三个已知字段并忽略未知顶层字段;缺失的
contractVersion统一规范化为1.0.0。 - 生产者只序列化三个字段。
- Gateway 保留已经校验的三字段失败响应和
errorCode,对调用方统一输出 HTTP200。 - 不增加双版本或版本协商;滚动迁移兼容只存在于 SDK consumer 边界,并以生产者全量迁移为删除条件。
- 生产者/消费者契约测试必须同时覆盖 HTTP
200成功与失败、未知顶层字段、成功data类型所有权,以及失败data为null和标准错误详情两种形态。