错误码
错误结构
接口错误沿用 OpenAI 风格:
json
{
"error": {
"code": "",
"message": "Invalid token (request id: 2026...)",
"type": "new_api_error"
}
}message:给人看的说明;code:机器可判断的错误码(可能为空);type:错误类别;request id:排查时提供给客服,能快速定位。
常见状态码
| 状态码 | 含义 | 常见原因 | 怎么处理 |
|---|---|---|---|
| 400 | 请求不合法 | JSON 语法错、messages 为空、参数类型不对 | 检查请求体;用最小请求复现 |
| 401 | 未认证 | 密钥缺失、错误、已删除 | 换有效密钥;检查 Bearer 空格 |
| 403 | 无权限 | 密钥被禁用、模型无权访问 | 控制台确认密钥状态与模型权限 |
| 404 | 资源不存在 | 路径错、模型 ID 不存在 | 确认 base_url 以 /v1 结尾;核对模型 ID |
| 413 | 请求过大 | 上下文超长 | 截断历史、减少 max_tokens |
| 429 | 限流 / 额度不足 | 并发过高、余额不足 | 退避重试;检查额度;申请提额 |
| 500 | 服务端错误 | 上游异常 | 退避重试;持续出现请联系客服 |
| 502 / 503 | 网关 / 上游不可用 | 临时故障 | 退避重试,避免雪崩 |
| 504 | 超时 | 上游响应慢 | 降低 max_tokens,重试 |
重试策略
只重试可能自愈的错误:429、500、502、503、504。
js
async function withRetry(fn, maxRetries = 3) {
let lastErr
for (let i = 0; i < maxRetries; i++) {
try {
return await fn()
} catch (e) {
lastErr = e
const status = e.status ?? e.response?.status
if (![429, 500, 502, 503, 504].includes(status)) throw e
const wait = Math.min(1000 * 2 ** i, 8000) + Math.random() * 300
await new Promise((r) => setTimeout(r, wait))
}
}
throw lastErr
}要点:
- 指数退避 + 随机抖动,避免同一时刻重试打爆;
- 最多 3 次,超过就把错误抛给业务层;
- 流式请求中断时,不要盲目重试整段,先确认是否已产生计费。
429 的两种含义
| 情况 | 表现 | 处理 |
|---|---|---|
| 速率限制 | 短时间大量请求 | 降并发、加队列、退避 |
| 额度不足 | 余额或配额耗尽 | 充值或调整额度 |
两者都返回 429,但处理方式不同,先看 message。
定位问题的最小请求
出问题时先用最小请求排除业务代码:
bash
curl -sS https://api.molicat.cc/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MOLICAT_API_KEY" \
-d '{"model":"YOUR_MODEL_ID","messages":[{"role":"user","content":"hi"}],"max_tokens":16}'- 能通 → 问题在业务代码或参数;
- 不通 → 密钥、模型、网络或服务端。
联系客服时提供
- 请求时间(精确到分钟);
request id;- 完整错误响应;
- 脱敏后的请求体;
- 是否稳定复现。