错误一致性是异步接口契约核心,需原样透传状态码、统一错误模型、保持结构跨阶段一致、避免静默吞没,并通过结构化约束保障语义无损传递。

异步处理中,错误一致性与状态码映射不是技术细节问题,而是接口契约的核心部分。如果源服务把目标服务返回的 422 Unprocessable Entity 错误悄悄转成 500 Internal Server Error,前端就无法区分是数据校验失败还是系统崩溃——这直接破坏了错误可诊断性。
明确错误来源与责任边界
在异步链路(如 API → 消息队列 → worker → 外部服务)中,每个环节都应清楚自己是否“代理错误”还是“产生错误”:
- 若只是转发请求(如网关、BFF 层),必须原样透传目标服务的状态码和错误结构,不能擅自降级为 5xx
- 若自身参与业务逻辑(如参数转换、权限校验),则需定义专属错误码(如
INVALID_INPUT),并映射到语义准确的 HTTP 状态码(如 400) - 对超时、连接失败等基础设施类异常,统一映射为 503 Service Unavailable 或 504 Gateway Timeout,而非笼统的 500
保持错误结构跨异步阶段一致
异步调用常跨越多个进程或网络跳转,错误信息容易在传递中丢失或变形。关键做法包括:
- 所有中间节点(如消息消费者、回调接收端)必须解析原始错误体,提取
error.code、message、request_id等字段,不依赖 HTTP 状态码做唯一判断 - 回调接口(如 Dify 的 webhook)收到失败通知时,应复用上游错误结构,仅补充本地上下文(如
"stage": "post-processing"),避免重写 message - 日志中记录完整错误链:从初始请求 ID 开始,串联各环节的 error.code 和耗时,便于追踪哪一环做了错误转换
用统一错误模型约束异步流程
定义一个轻量但强制的错误响应规范,所有异步参与者都必须遵守:
- 响应体始终为 JSON,顶层固定字段:
error(对象)、timestamp、request_id -
error.code使用大写下划线命名(如CONNECTION_TIMEOUT),不与 HTTP 状态码混用 -
error.status_code字段显式声明应返回的 HTTP 状态码,供网关层读取并设置响应头 - 异步任务结果回调(如成功/失败通知)也采用同一结构,确保前端或下游服务无需区分同步/异步路径
避免异步错误被静默吞没
异步场景下,错误极易因缺少回调注册、未监听 Promise rejection 或忽略 channel 错误而消失:
- Node.js 回调风格:严格遵循“错误优先”,并在每个回调入口检查
if (err),不跳过 - Promise / CompletableFuture 链:每个链路末尾加
.catch()或.exceptionally(),生产环境必须监听unhandledRejection事件 - 消息队列消费端:失败时拒绝消息(NACK)并设置死信队列,而不是简单跳过;记录原始 payload 和错误堆栈
错误一致性不是靠约定,而是靠结构化约束和自动化校验。状态码只是表层信号,真正重要的是错误语义能否在整条异步链路上无损传递。











