错误处理与请求追踪
平台三种错误响应形态对照、错误码与 HTTP 状态码排查、request id 请求追踪。
错误响应的三种形态
平台存在三种不同的错误响应形态,适用端点各不相同。按下表区分,不要假设所有端点共用一种结构:
| 形态 | 结构特征 | 适用端点 | 解析路径 |
|---|---|---|---|
| 模型接口错误对象 | 嵌套 error 对象,含 message/type/code | 绝大多数 /v1、/v2 同步接口(chat、images、audio、embeddings、models 等) | body.error.message |
| 任务错误信封 | 顶层扁平 code/message/data,无 error 包装、无 type | 异步任务类端点(视频任务的提交与查询等) | body.message |
| 管理接口结果 | success 布尔 + message | /api 前缀的管理接口 | body.success 判成败 |
body.error.message 解析所有端点会在任务类接口上静默失败——
拿到的 error 是 undefined 而非报错信息。接入任务类端点时必须按扁平信封单独解析。模型接口(/v1、/v2)
错误响应统一为 OpenAI 风格的 error 对象:
{
"error": {
"code": "model_not_found",
"message": "模型 xxx 暂无可用渠道,请稍后再试 (request id: 20260728144017316963600KfI3f8bQ)",
"type": "jimu_api_error"
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
message | string | 人类可读的错误描述,末尾统一附带 (request id: ...) |
type | string | 错误类别,见下表 |
code | string | 机器可读的错误码;鉴权失败等中间件直接拒绝的场景为空串 "",业务错误时非空 |
param | string | 出错的请求参数名,多数场景为空串 |
type 的取值:
| 值 | 含义 |
|---|---|
jimu_api_error | 平台侧错误:鉴权失败、额度不足、无可用渠道、参数校验失败等 |
invalid_request_error | 请求校验失败的专用类别(如路径参数缺失、格式转换失败),同为平台侧错误 |
openai_error | 上游 OpenAI 兼容渠道返回的错误,原样透传其 code |
claude_error | 上游 Anthropic 渠道返回的错误 |
gemini_error | 上游 Gemini 渠道返回的错误 |
midjourney_error | 上游 Midjourney 渠道返回的错误 |
rerank_error | 上游 Rerank 服务返回的错误 |
upstream_error | 无法归类到具体厂商的上游错误 |
type 仅用于归类,程序判断错误语义应以 code 为准(如 model_not_found)。code 非空时是稳定的机器可读标识,适合程序判断。常见取值:
| code | 含义 |
|---|---|
invalid_request | 请求体不合法或参数校验失败 |
model_not_found | 该模型无可用渠道(模型名错误或账号无权访问) |
access_denied | 无权访问:套餐不含该模型、IP 不在令牌白名单等 |
insufficient_user_quota | 账号额度不足 |
channel:no_available_key | 渠道侧密钥不可用(平台侧问题,可报障) |
channel:all_in_cooldown | 所有渠道触发限流冷却,稍后重试 |
sensitive_words_detected | 提示词命中敏感词拦截 |
Anthropic 原生接口的错误变体
/v1/messages 等 Claude 原生端点返回 Claude 风格的错误结构:
{
"type": "error",
"error": {
"type": "jimu_api_error",
"message": "未提供令牌 (request id: 20260728144017307942003YcfgsXq)"
}
}
error.type 的取值与上表一致,message 同样附带 request id。
任务类接口(异步任务)
视频生成等异步任务端点(任务提交与结果查询,如 /v1/video/generations/{task_id}、/v1/videos/{task_id})
不使用嵌套 error 对象,而是返回顶层扁平信封:
{
"code": "task_not_exist",
"message": "task_not_exist",
"data": null
}
- 顶层字段为
code/message/data,没有error包装、没有type字段 - 任务不存在时 HTTP 状态码是 400 而非 404,不要用状态码区分「路由不存在」与「任务不存在」
- 任务提交失败(如配额不足 403
quota_not_enough、上游负载饱和 429)同样是此信封 message不附带 request id;报障时请提供task_id与请求时间
常见任务类 code:task_not_exist(任务不存在)、task_origin_not_exist(上游任务已不存在)、
quota_not_enough(配额不足)。
管理接口(/api)
管理接口不使用 error 对象,而是返回:
{
"success": false,
"message": "无权进行此操作,未登录且未提供 access token"
}
判断管理接口成败以 success 布尔值为准,不要只依赖 HTTP 状态码:
部分校验失败场景 HTTP 状态码仍为 200,仅靠 success: false 标识失败。
常见 HTTP 状态码
| 状态码 | 含义 | 排查建议 |
|---|---|---|
| 400 | 请求参数不合法 | 按 message 修正请求体;注意各端点的必填参数 |
| 401 | 未提供令牌 / 令牌无效 / 未登录 | 检查 Authorization 头是否携带完整 sk- 令牌;管理接口检查登录会话与 Jimu-Api-User |
| 403 | 已鉴权但无权访问 | 模型不在令牌或套餐允许范围内;令牌设了 IP 白名单而当前 IP 不在列;用户被封禁 |
| 404 | 路径不存在 | 核对路径与方法(如 GET 误用 POST) |
| 413 | 请求体过大 | 减小输入体积(如图片尺寸、上下文长度) |
| 429 | 触发限流 | 平台级速率限制或全部渠道冷却;降低并发、指数退避重试 |
| 500 | 平台内部错误 | 记录 request id 报障;可先重试一次排除瞬时故障 |
| 503 | 模型无可用渠道 | 核对模型名拼写;确认账号有权访问该模型(见 模型列表 v2) |
重试策略:429 与 5xx 可指数退避重试(建议 1s、2s、4s,最多 3 次); 400、401、403 属于确定性错误,修正请求前不要重试。
关于限流的稳定口径:具体阈值由账号与平台配置动态决定,不承诺固定 RPM/TPM 值;
响应不提供 Retry-After 或 X-RateLimit-* 头,不要依赖它们。
触发 429 时按指数退避并加入随机抖动(jitter),同时收敛客户端并发。
request id
每个请求都会分配唯一 request id,通过两种方式返回:
- 响应头
X-Jimu-Request-Id——成功与失败响应都携带,应优先从这里读取 - 错误响应
message末尾的(request id: ...)后缀——与响应头是同一个 ID,仅在出错时出现
排查问题或联系支持时,请提供 request id 与大致请求时间, 平台可据此在服务端日志中精确定位该次请求的完整链路(含上游渠道与原始响应)。