文档
错误
Kunavo 返回符合 OpenAI 格式的错误负载,并通过 HTTP 状态码指示是否应重试。遵循 OpenAI SDK 的标准错误处理方式即可。
每个非 2xx 响应都采用相同的 JSON 结构,即 OpenAI 标准格式。程序化处理时匹配 error.code,制定重试策略时匹配 status_code。
错误负载
{
"error": {
"message": "Model 'xyz-2025' is not available",
"type": "model_not_found",
"code": "model_not_found",
"param": null
}
}| 字段 | 类型 | 备注 |
|---|---|---|
message | string | 人类可读。可安全记录日志;绝不包含机密。 |
type | string | 粗略类别(authentication_ |
code | string | 更精细的标识符。用于编写程序分支逻辑。 |
param | string|null | 如果错误与特定字段有关,这里会指出该字段。 |
HTTP 状态码
| HTTP | 含义 | Retry? |
|---|---|---|
| 400 | invalid_ — 请求负载格式错误。 | 否 — 修正请求。 |
| 401 | authentication_ — API 密钥无效、缺失或已撤销。 | 否 — 轮换密钥。 |
| 402 | insufficient_ — 钱包余额为零(code: insufficient_)或已达到月度上限。 | 不能 — 请前往 /app/billing 充值。例外情况:Retry-After 标头表示自动充值正在处理中;处理完成后重试。 |
| 403 | permission_ — 密钥有效,但其 IP 允许列表未包含你的 IP。 | 否 — 从允许的地址发起调用。 |
| 404 | model_ — 模型 ID 未知或已停用。 | 否 — 检查 /v1/models。 |
| 404 | missing_ — 在 api./v1,或向裸主机名发送了 POST 请求。 | 否 — 将 base URL 设为 https://api. |
| 404 | unknown_url — /v1 下该路径没有端点;错误消息会指出最接近的端点。 | 否 — 修正路径。 |
| 408 | 客户端请求超时。 | 是,但需注意幂等性。 |
| 422 | upstream_422 — 上游拒绝了你的输入(例如,不支持的尺寸)。 | 否 — 调整输入。 |
| 429 | 触发速率限制 — 并发调用过多。 | 是 — 使用指数退避。 |
| 500 | Kunavo 内部错误。 | 是 — 短暂退避。 |
| 502 | upstream_ — 上游提供商故障。 | 是 — 使用指数退避。 |
| 504 | 任务超时(图像 / 视频生成超出了轮询预算)。 | 可以,但仍会产生费用。 |
失败的调用(4xx + 5xx)不计费。
usage_logs 中的成本记录为 $0。例外情况:长时间运行的任务 API 出现 504 超时时,如果任务已完成但我们未能交付结果,可能会显示上游成本——这种情况很少见。常见错误代码
authentication_error
- 忘记设置
Authorization: Bearer ...标头。 - API key 已在
/app/keys撤销。 - 密钥仍使用错误的前缀(必须以
sk-kn-开头)。
insufficient_quota
- 钱包余额不足,无法处理此请求 →
error.code为insufficient_balance;错误信息会附带钱包当前余额(balance_usd)、此请求的预留金额(needed_usd)以及两个链接:topup_url会打开已预先填入充值金额的账单页面,auto_recharge_url会打开自动充值设置页面。点击任一链接本身都不会产生扣款。 - 已达到单个密钥的月度上限。该上限会在每个日历月月初(UTC)重置。请前往
/app/keys提高上限。
{
"error": {
"message": "Wallet balance is too low for this request. Top up at https://kunavo.com/app/billing — or turn on auto-recharge there, and a saved card refills the wallet before requests are refused.",
"type": "insufficient_quota",
"code": "insufficient_balance",
"param": null,
"balance_usd": 0.0142,
"needed_usd": 0.0381,
"topup_url": "https://kunavo.com/app/billing?topup=20",
"auto_recharge_url": "https://kunavo.com/app/billing?autorecharge=1&src=api_402"
}
}遇到 insufficient_balance 时请停止重试,除非响应中包含 Retry-After 标头——这表示自动充值正在从您保存的银行卡扣款,几秒后使用相同请求即可成功。
permission_error
- 该密钥设置了 IP 允许列表,而您的调用来自列表之外的地址。错误消息会指出我们检测到的地址——请在
/app/keys添加该地址(或其 CIDR 网段),或完全移除允许列表以允许任何地址。 - 将智能体迁移到新主机、新 NAT 网关,或换到不同网络上的笔记本电脑,都会改变该地址。未设置允许列表的密钥不会因此被拒绝。
model_not_found
- Slug 拼写错误。规范列表请使用 /models。
- 模型目前已停用(上游服务中断或正在审核定价)。
upstream_error
表示上游模型提供商返回了一个我们无法转换为更具体代码的错误。响应正文包含原始消息。常见原因:
- 提供商侧过载。
- 内容审核未通过(请尝试更换提示词)。
- 区域或可用性限制。
重试策略
最简单且可靠的模式:仅在 429 / 5xx 时使用带抖动的指数退避。
import time, random
from openai import OpenAI, RateLimitError, APIError
client = OpenAI(api_key=os.environ["KUNAVO_API_KEY"], base_url="https://api.kunavo.com/v1")
def call_with_retry(call, max_attempts=5):
for attempt in range(max_attempts):
try:
return call()
except RateLimitError:
if attempt + 1 == max_attempts: raise
# 429: exponential backoff with jitter
time.sleep(min(2 ** attempt, 30) + random.random())
except APIError as e:
if e.status_code and 500 <= e.status_code < 600 and attempt + 1 < max_attempts:
time.sleep(min(2 ** attempt, 30) + random.random())
else:
raise
result = call_with_retry(lambda: client.chat.completions.create(
model="claude-haiku-4-5",
messages=[{"role": "user", "content": "hi"}],
))- 每次尝试的等待时间上限为 30 秒,总尝试次数上限为 5 次。
- 不要重试 4xx(408 和 429 除外)。这样只会浪费时间。
- 图像和视频生成都不是幂等的:每次重试都是一次新的生成,成功才计费。失败的调用从未计费,因此重试它们是安全的。对于视频,
POST /v1/videos支持Idempotency-Key请求头:用相同的幂等键重复提交,会返回第一个任务。 - 对于在你自己的代码中带有副作用的聊天请求,请在应用层通过幂等键进行去重。
在控制面板中调试
每次 API 调用——无论成功还是失败——都会显示在 /app/usage。点击任意行可查看完整的请求 / 响应详情页:
- 返回给客户端的 HTTP 状态码。
- 上游错误代码(如适用)。
- 延迟、请求 IP、user-agent。
- 按状态筛选有助于发现规律(例如,特定模型的所有 422 错误)。
报告事故
如果某个本应正常工作的模型持续出现 5xx 错误,请发送邮件至 support@kunavo.com,并提供:
- 模型 slug 和一份示例请求正文(请隐去机密信息)。
- 故障发生的时间段。
- 响应中的错误
code+message。 - 如有可能,提供来自
/app/usage/[id]的使用日志链接。
一个工作日内回复;对紧急且影响收入的问题会更快处理。