错误处理
错误响应格式和常见错误码
错误响应格式
当 API 请求失败时,Swape.AI 返回以下结构的 JSON 错误响应:
Web API 错误
所有 /web/v1 端点以 Swape.AI 的标准格式返回错误:
{
"success": false,
"data": null,
"error": {
"code": "UNAUTHORIZED",
"msg": "API Key 无效或已被撤销",
"detail": "可选的附加详情"
}
}| 字段 | 类型 | 说明 |
|---|---|---|
success | boolean | 错误响应始终为 false。 |
data | null | 错误响应始终为 null。 |
error.code | string | 用于程序化错误处理的字符串错误码(如 "BAD_REQUEST"、 "UNAUTHORIZED")。 |
error.msg | string | 人类可读的错误消息,描述出了什么问题。 |
error.detail | string | 可选的附加详情(如验证错误的具体信息)。为空时省略。 |
代理 API 错误
代理端点( /v1/responses、 /v1/messages、 /v1beta/models/*)以匹配请求的 API 格式返回错误,以确保 SDK 的错误处理按预期工作。
OpenAI 格式 (/v1/responses):
{
"error": {
"message": "提供的 API Key 无效",
"type": "invalid_request_error",
"code": "invalid_api_key"
}
}Anthropic 格式 (/v1/messages):
{
"type": "error",
"error": {
"type": "authentication_error",
"message": "提供的 API Key 无效"
}
}Gemini 格式 (/v1beta/models/*):
{
"error": {
"code": 401,
"message": "提供的 API Key 无效",
"status": "UNAUTHENTICATED"
}
}错误码
错误码是字符串标识符,用于 Web API 响应中的 error.code 字段。
通用错误
| 错误码 | HTTP 状态码 | 说明 |
|---|---|---|
BAD_REQUEST | 400 | 请求体格式错误或缺少必需字段。 |
UNAUTHORIZED | 401 | 认证失败 — 凭据无效或缺失。 |
FORBIDDEN | 403 | 权限不足 — 没有足够的访问权限。 |
NOT_FOUND | 404 | 请求的端点不存在。 |
METHOD_NOT_ALLOWED | 405 | 该端点不支持此 HTTP 方法。 |
CONFLICT | 409 | 发生冲突(如并发修改)。 |
TOO_MANY_REQUESTS | 429 | 超出频率限制。等待后使用指数退避重试。 |
INTERNAL_ERROR | 500 | 发生意外的内部错误。 |
SERVICE_UNAVAIL | 503 | 服务暂时不可用。 |
CONFIG_NOT_READY | 503 | 所需的系统配置尚未初始化。 |
认证错误
| 错误码 | HTTP 状态码 | 说明 |
|---|---|---|
INVALID_TOKEN | 401 | 访问令牌无效或格式错误。 |
TOKEN_EXPIRED | 401 | 访问令牌已过期。使用刷新令牌获取新令牌。 |
INVALID_CREDENTIALS | 401 | 提供的邮箱或密码不正确。 |
PASSWORD_NOT_SET | 401 | 该账户未设置密码(如仅通过 OAuth 注册的账户)。 |
资源错误
| 错误码 | HTTP 状态码 | 说明 |
|---|---|---|
RESOURCE_NOT_FOUND | 404 | 请求的资源(模型、API Key、用户等)不存在。 |
RESOURCE_EXISTS | 409 | 相同标识符的资源已存在。 |
MODEL_IN_USE | 409 | 无法删除该模型,因为它已绑定到活跃的渠道。 |
PROVIDER_HAS_MODELS | 409 | 无法删除该提供商,因为仍有关联的模型。 |
验证错误
| 错误码 | HTTP 状态码 | 说明 |
|---|---|---|
VALIDATION_FAILED | 422 | 请求参数验证失败。检查 error.detail 字段获取具体信息。 |
INVALID_BODY | 400 | 请求体无效或无法解析。 |
INVALID_QUERY | 400 | 一个或多个查询参数无效。 |
INVALID_PARAMETER | 400 | 特定参数值无效。 |
MISSING_PARAMETER | 400 | 缺少必需参数。 |
EMPTY_UPDATE | 400 | 更新请求中不包含任何需要修改的字段。 |
PAYLOAD_TOO_LARGE | 413 | 请求负载超过允许的最大大小。 |
业务错误
| 错误码 | HTTP 状态码 | 说明 |
|---|---|---|
INSUFFICIENT_BALANCE | 400 (Web API) / 402 (Proxy) | 账户余额不足以处理此请求。在控制台中充值。Web API 端点返回 HTTP 400;代理端点( /v1/responses、 /v1/messages、 /v1beta/models/*)返回 HTTP 402。 |
SELF_OPERATION | 400 | 不能对自己的账户执行此操作(如管理员不能删除自己)。 |
CAPTCHA_FAILED | 400 | 验证码验证失败,请重试。 |
OTP_INVALID | 400 | 提供的一次性密码(OTP)无效或已过期。 |
代理网关错误
使用代理端点( /v1/responses、 /v1/messages、 /v1beta/models/*)时,错误以 provider 特定格式返回,而非标准 Web API 格式。HTTP 状态码指示错误类型:
| HTTP 状态码 | 含义 | OpenAI 错误类型 | Anthropic 错误类型 | Gemini 错误状态 |
|---|---|---|---|---|
| 400 | 请求错误 | invalid_request_error | invalid_request_error | INVALID_ARGUMENT |
| 401 | API Key 无效 | invalid_request_error | authentication_error | UNAUTHENTICATED |
| 402 | 余额不足 | billing_error | billing_error | RESOURCE_EXHAUSTED |
| 403 | 配额超限 | invalid_request_error | permission_error | PERMISSION_DENIED |
| 404 | 未找到 | invalid_request_error | not_found_error | NOT_FOUND |
| 429 | 频率限制 | rate_limit_error | rate_limit_error | RESOURCE_EXHAUSTED |
| 5xx | 服务器错误 | api_error | api_error | INTERNAL |
HTTP 状态码
OpenModel 使用标准 HTTP 状态码:
| 状态码 | 含义 |
|---|---|
| 200 | OK -- 请求成功。 |
| 400 | Bad Request -- 请求参数无效。 |
| 401 | Unauthorized -- API Key 无效或缺失。 |
| 402 | Payment Required -- 余额不足。 |
| 403 | Forbidden -- 权限不足。 |
| 404 | Not Found -- 资源不存在。 |
| 405 | Method Not Allowed -- 该端点不支持此 HTTP 方法。 |
| 409 | Conflict -- 资源冲突(如重复或正在使用中)。 |
| 413 | Payload Too Large -- 请求体超过大小限制。 |
| 422 | Unprocessable Entity -- 验证失败。 |
| 429 | Too Many Requests -- 超出频率限制。 |
| 500 | Internal Server Error -- 服务器内部错误。 |
| 502 | Bad Gateway -- 上游提供商错误。 |
| 504 | Gateway Timeout -- 上游提供商超时。 |
错误处理
重试策略
对于暂时性错误(429、500、502、503、504),实现带抖动的指数退避:
import time
import random
from openai import OpenAI, APIError, RateLimitError
client = OpenAI(
base_url="https://api.openmodel.ai/v1",
api_key="your-api-key",
)
def create_with_retry(max_retries=3):
for attempt in range(max_retries):
try:
return client.responses.create(
model="gpt-4o",
input="你好,世界!",
)
except RateLimitError:
if attempt == max_retries - 1:
raise
wait = (2 ** attempt) + random.random()
print(f"频率受限,{wait:.1f}秒后重试...")
time.sleep(wait)
except APIError as e:
if e.status_code in (500, 502, 503, 504) and attempt < max_retries - 1:
wait = (2 ** attempt) + random.random()
print(f"提供商错误,{wait:.1f}秒后重试...")
time.sleep(wait)
else:
raise
response = create_with_retry()最佳实践
- 通过错误码进行程序化判断 -- 使用
error.code(Web API)或格式特定的错误类型(代理 API)进行流程控制,而不是人类可读的错误消息。 - 实现指数退避 -- 对于频率限制(429)和服务器错误(500、502、503、504),在重试之间使用递增的延迟时间。
- 设置合理的超时时间 -- 配置客户端超时时间,优雅地处理上游提供商响应慢的情况。
- 监控你的用量 -- 使用仪表板跟踪 API Key 的使用情况,在达到频率限制或余额耗尽之前设置警报。
- 记录错误响应 -- 记录完整的错误响应用于调试,尤其是间歇性问题。