错误处理
本文档规范任务失败时的错误信息处理,包括错误分类、识别规则和标准消息格式。
错误处理流程
API响应/异常 → 识别错误类型 → 生成标准错误消息 → 存入 task.error
↓
保存原始响应 → 存入 task.errorDetail (JSON)错误类型定义
| 错误类型 | 错误码 | 标准消息 | 说明 |
|---|---|---|---|
| 内容审核 | CONTENT_FILTERED | 内容被安全过滤器拒绝 | 提示词触发内容审核 |
| 配额耗尽 | QUOTA_EXCEEDED | API 配额已用尽 | 账户余额不足或达到限制 |
| 请求过频 | RATE_LIMITED | 请求过于频繁,请稍后重试 | 触发速率限制 |
| 认证失败 | AUTH_FAILED | API 密钥无效或已过期 | 401/403 认证问题 |
| 模型不可用 | MODEL_UNAVAILABLE | 模型暂不可用 | 模型名称错误或服务下线 |
| 参数错误 | INVALID_PARAMS | 请求参数无效 | 提示词格式/图片格式等问题 |
| 上游超时 | UPSTREAM_TIMEOUT | 上游服务响应超时 | 中转站或原始API超时 |
| 网络错误 | NETWORK_ERROR | 网络连接失败 | DNS/连接/SSL等网络问题 |
| 空响应 | EMPTY_RESPONSE | 未收到有效响应 | API返回空内容 |
| 解析失败 | PARSE_ERROR | 响应格式异常 | 无法从响应中提取图片 |
| 保存失败 | SAVE_FAILED | 图片保存失败 | 本地存储问题 |
| 未知错误 | UNKNOWN | 生成失败 | 无法分类的错误 |
错误识别规则
按优先级从高到低匹配:
1. 内容审核 (CONTENT_FILTERED)
识别条件(满足任一):
- HTTP 状态码
400且响应包含safety、blocked、filtered、content_policy - 响应包含
empty_response且no meaningful content in candidates - 响应
finishReason为SAFETY或BLOCKED - 错误消息包含
content policy、safety filter、moderation
示例响应:
json
{
"error": {
"message": "received empty response from Gemini: no meaningful content in candidates",
"code": "channel:empty_response"
}
}2. 配额耗尽 (QUOTA_EXCEEDED)
识别条件:
- HTTP 状态码
402或429(需排除内容审核) - 响应包含
quota、balance、insufficient、exceeded - 错误码包含
quota、billing
示例响应:
json
{
"error": {
"message": "You exceeded your current quota",
"type": "insufficient_quota"
}
}3. 请求过频 (RATE_LIMITED)
识别条件:
- HTTP 状态码
429(排除配额和内容审核后) - 响应包含
rate limit、too many requests
4. 认证失败 (AUTH_FAILED)
识别条件:
- HTTP 状态码
401或403 - 响应包含
unauthorized、invalid.*key、authentication
5. 模型不可用 (MODEL_UNAVAILABLE)
识别条件:
- HTTP 状态码
404 - 响应包含
model.*not.*found、does not exist
6. 参数错误 (INVALID_PARAMS)
识别条件:
- HTTP 状态码
400(排除内容审核后) - 响应包含
invalid、malformed、missing required
7. 上游超时 (UPSTREAM_TIMEOUT)
识别条件:
- HTTP 状态码
504或408 - 响应包含
timeout、timed out - 错误类型为
TimeoutError
8. 网络错误 (NETWORK_ERROR)
识别条件:
- 无 HTTP 响应(请求未到达服务器)
- 错误类型为
FetchError、NetworkError - 错误包含
ECONNREFUSED、ENOTFOUND、ETIMEDOUT
9. 空响应 (EMPTY_RESPONSE)
识别条件:
- HTTP 状态码
200但响应体为空 - 响应中
candidates数组为空(排除内容审核后) - 响应中
data数组为空
10. 解析失败 (PARSE_ERROR)
识别条件:
- HTTP 状态码
200但无法从响应中提取图片 URL/Base64 - 响应格式与预期不符
错误详情
错误详情通过日志文件系统提供。
日志存储结构
logs/
└── YYYY-MM-DD/ # 按日期分组
└── {taskId}/ # 按任务ID分组
├── request.json # 请求数据
└── response.json # 响应数据日志文件格式
request.json:
json
{
"timestamp": "2024-01-01T12:00:00.000Z",
"url": "https://api.example.com/...",
"method": "POST",
"body": { ... }
}response.json:
json
{
"timestamp": "2024-01-01T12:00:05.000Z",
"status": 200,
"statusText": "OK",
"data": { ... },
"error": "错误信息(如有)"
}注意:网络错误、超时等无响应情况下,response.json 可能不存在。
前端展示规范
错误卡片
┌─────────────────────────────────┐
│ ❌ 失败 │
│ 内容被安全过滤器拒绝 │
└─────────────────────────────────┘新增错误类型流程
当遇到无法分类的新错误时:
- 查看日志中的原始响应
- 分析错误特征(状态码、错误消息、错误码)
- 判断是否属于已有类型
- 是:添加新的识别规则
- 否:新增错误类型
- 更新本文档
- 更新代码中的错误识别逻辑
参考:常见中转站错误格式
标准 OpenAI 格式
json
{
"error": {
"message": "...",
"type": "...",
"param": "...",
"code": "..."
}
}MJ-Proxy 格式
json
{
"code": 21,
"description": "任务已存在"
}中转站包装格式
json
{
"error": {
"message": "received empty response from Gemini: ...",
"type": "channel_error",
"code": "channel:empty_response"
}
}