适用范围
约束所有接口与管理界面的错误表达,以及调用方对错误的应对行为。
不约束:日志与堆栈的格式;具体错误码字面值(由各功能在上表类别下自行定义);面向内部排障的诊断文本。
规范条款
分类的唯一性
- 每个错误必须归属且仅归属下列一类;必须不存在无法归类的错误。
| 类别 | 含义 | 客户端必须做什么 | 可重放 |
|---|
| 形状 / 版本错误 | 请求未被解析,无副作用 | 修正请求 | 必须不重放 |
| 认证失败 | 凭据不可用或已失效 | 重新获取凭据 | 换凭据后可重试 |
| 权限不足 | 身份有效,但无权做该操作 | 转交有权的人 | 必须不重放 |
| 作用域不符 | 凭据有效但作用于非授权作用域 | 停止;必须不探测其它作用域 | 必须不重放 |
| 状态冲突 | 本次提交未生效,更新的状态胜出 | 先同步当前状态再决定 | 同步后可重试 |
| 身份 / 租约冲突 | 已有有效持有者,或持有已失效 | 不抢占;失约方先收束 | 视持有情况 |
| 结果冲突 | 已存在不同结果,不可覆盖 | 停止;交人处理 | 必须不重放 |
| 无工作 | 当前没有可处理的对象 | 正常结束本轮 | 换新幂等身份后可重试 |
| 不可用 | 依赖不可达或暂不可服务 | 退避后重试 | 退避后可重试 |
| 未知错误 | 无法归类 | 停止并上报 | 必须不重放 |
- 错误类别必须由稳定标识表达;必须不要求调用方解析错误文本判定类别。
- 「无工作」必须作为正常结果表达,必须不伪装成故障。
- 任何错误必须不携带敏感值:凭据、内部路径、宿主信息、原始堆栈、其它作用域的存在性证据。
可重放性
- 每个错误必须显式声明是否可重放;必须不让调用方自行推断。
- 明确失败必须不重放:形状错误、权限不足、作用域不符、结果冲突、未知错误。
- 只有不可用与模糊响应(超时、连接中断)可以按原幂等身份重放。
副作用边界
- 错误返回时必须明确"是否有副作用发生":
- 形状 / 版本错误、认证失败、权限不足、作用域不符 → 必须无副作用;
- 状态冲突 → 必须本次提交未生效;
- 身份 / 租约冲突 → 必须未改变状态。
- 必须不出现"部分生效"的错误返回;无法保证原子性时必须改为先校验后提交。
枚举与封闭
- 各功能自定义的错误码必须:在某类别之下、稳定、不复用、删除即删除(必须不保留别名或"旧值"标注)。
- 稳定失败码必须是白名单;必须不接受任意文本作为错误码回传。
- 新增类别必须先改本规格,必须不由单个功能自行扩展。
违反时的失败语义
| 违反情形 | 必须的行为 |
|---|
| 错误无法归类 | 视为规格违反;必须归入"未知错误"并补归类 |
| 错误文本用于判定 | 视为规格违反;必须改为稳定标识 |
| 错误携带敏感值 | 必须视为安全缺陷处理 |
| 明确失败被标记可重放 | 视为规格违反;必须改为不可重放 |
| 部分生效返回 | 视为规格违反;必须改为原子或前置校验 |
| 单功能新增类别 | 必须撤回,改为先评审本规格 |
校验方式
| 校验对象 | 判据 | 失败表现 |
|---|
| 分类完备 | 每个错误码必须映射到本规格的某一类别 | 无法映射即失败 |
| 稳定标识 | 响应必须含稳定错误标识,且不得要求解析文本 | 缺失即失败 |
| 无副作用保证 | 形状 / 认证 / 权限 / 作用域错误必须不改变任何状态 | 状态变化即失败 |
| 重放边界 | 明确失败按原幂等身份重放必须不被接受 | 被接受即失败 |
| 无工作语义 | 无工作必须表达为正常结果,不得为故障 | 表达为故障即失败 |
| 敏感值禁入 | 错误响应不得含凭据、路径、宿主信息、堆栈 | 出现即失败 |
| 作用域不泄漏 | 作用域不符必须与"不存在"同形 | 可区分即失败 |
相关规格