错误
Lovely Router 返回的每个 HTTP 状态码、每种 API 格式的错误响应体,以及何时、如何重试。
Lovely Router 使用标准的 HTTP 状态码。2xx 表示成功,4xx 表示请求需要修改(或者你的账户需要充值),5xx 或 429 表示值得重试的临时问题。响应体会以你所调用 API 的格式说明原因,因此官方 SDK 会抛出它们惯常的异常。
状态码#
| 状态码 | 含义 | 常见原因 | 是否重试? |
|---|---|---|---|
400 | 请求错误 | 请求体不是有效的 JSON。模型拒绝了某个参数,例如 max_tokens 超出其上限。工具输入缺少必填字段。x-lovely-group 未知。 | 否。修正请求。 |
401 | 未认证 | 密钥缺失、输错、已吊销或已过期 | 否。检查密钥。 |
402 | 需要付款 | 余额为 $0。密钥达到了消费上限。余额不足以支付一次运行的最高费用。 | 充值或调高上限之后 |
403 | 禁止访问 | 模型不在密钥的白名单中 | 否 |
404 | 未找到 | 模型 id 未知、该 API 格式不提供此模型、端点未知、工具或运行不存在 | 否 |
405 | 方法不允许 | 对浏览器保险库或文件端点使用了错误的 HTTP 方法 | 否 |
409 | 冲突 | 回复了一个并未在等待该回复、或已经结束的浏览器运行。文件存储已达上限。 | 否。检查运行的状态。 |
413 | 请求体过大 | 提示词对该模型来说过长。工具输入超过 50 KB。文件超过 10 MB。 | 否。减小大小。 |
422 | 无法处理 | 模型拒绝了请求的内容 | 否 |
429 | 请求过多 | 密钥的频率或并发限制、模型容量繁忙、已有 10 个运行在进行中、规划服务限额 | 是,等待 retry-after 之后 |
500 | 内部错误 | Lovely Router 内部发生意外错误 | 是,配合退避 |
502 | 网关错误 | 模型在尝试过的所有渠道上都失败了。工具无法启动(不会向你扣费)。 | 是,配合退避 |
503 | 服务不可用 | 某个数据工具或浏览器智能体暂时不可用 | 是,配合退避 |
其他任何 5xx 都按 502 处理。在到达模型之前就被拒绝的请求所产生的错误(无效 JSON 导致的 400、401、402、403、模型未知导致的 404,以及密钥限制导致的 429)永远不会计费。
模型端点的错误响应体#
模型端点以你所调用 API 的格式返回错误。下面每个标签页展示的是同一个 401。
{"type": "error", "error": {"type": "authentication_error", "message": "Invalid or revoked API key"}}每个状态码对应的错误 type(Anthropic 和 OpenAI)或 status(Gemini):
| 状态码 | Anthropic error.type | OpenAI error.type 和 error.code | Gemini error.status |
|---|---|---|---|
400 | invalid_request_error | invalid_request_error | INVALID_ARGUMENT |
401 | authentication_error | authentication_error | UNAUTHENTICATED |
402 | billing_error | insufficient_quota | RESOURCE_EXHAUSTED |
403 | permission_error | permission_denied | PERMISSION_DENIED |
404 | not_found_error | not_found_error,端点未知时为 not_found | NOT_FOUND |
413、422 | invalid_request_error | invalid_request_error | INVALID_ARGUMENT |
429 | rate_limit_error | rate_limit_exceeded | RESOURCE_EXHAUSTED |
500 | api_error | api_error | INTERNAL |
502、503 | api_error | api_error | UNAVAILABLE |
504 | api_error | api_error | DEADLINE_EXCEEDED |
在 Gemini 响应体中,error.code 始终等于 HTTP 状态码。请根据状态码而不是 status 字符串做分支判断。在读取请求之前产生的错误,例如端点未知或网关意外出错,同样使用你所调用端点的格式。
你可能看到的消息#
| 状态码 | 消息 |
|---|---|
400 | Body must be JSON |
400 | Unknown group 'xyz' |
400、413、422 | 模型自己给出的原因,例如 prompt is too long |
401 | Missing API key、Invalid or revoked API key、This API key has expired |
402 | Insufficient balance. Top up at the dashboard. |
402 | This API key has reached its spend limit. |
403 | This API key is not allowed to use 'gpt-6.1-sol'. |
404 | Model 'gpt-9' is not available. See GET /v1/models. |
404 | Unknown endpoint /v1/embeddings |
429 | This API key has reached its rate or concurrency limit. |
429 | All upstream capacity for this model is busy. Retry shortly. |
502 | The model provider returned an error. Please retry. |
每个错误响应都带有 x-lovely-request-id 响应头,包括在到达模型之前就被拒绝的请求(密钥无效、余额为零、模型未知)。联系支持时请提供它。
工具和浏览器智能体的错误响应体#
/v1/tools 和 /v1/browser 的所有错误都使用同一种格式:一个机器可读的 type,加上一条写给人看的消息。
{"error": {"type": "insufficient_quota", "message": "Insufficient balance: this run can cost up to $0.3000 (100 results). Lower max_results or top up."}}| 状态码 | error.type | 示例 |
|---|---|---|
400 | invalid_request_error | Missing required input: query. See GET /v1/tools/{id}.、"start_url" must be an http(s) URL |
401 | authentication_error | Missing, invalid or revoked API key、This API key has expired |
402 | insufficient_quota | 余额不足以支付运行的最高费用,或会超出密钥的消费上限 |
404 | not_found | Unknown tool 'x'. Find one with POST /v1/tools/discover.、No such run |
405 | invalid_request_error | 对保险库或文件端点使用了错误的方法 |
409 | invalid_request_error | This run is not waiting for a reply、This run has finished |
413 | invalid_request_error | Input too large、Files are limited to 10 MB |
429 | rate_limit_exceeded | At most 10 tool runs may be running at once. |
500 | api_error | Internal error |
502、503 | tool_unavailable | The tool is temporarily unavailable; you were not charged. Try again shortly. |
已经启动、随后失败的运行不算 HTTP 错误。返回的运行对象中,status 为 failed、timed_out 或 stopped,并带有一条 error 消息,你只为已返回的结果付费。参阅运行工具。
流式输出中的错误#
流一旦开始,状态码就已经是 200,因此错误会改为以流中的事件形式到达。首个 token 之前发生的失败会切换到其他渠道重试,所以通常你看到的流要么成功,要么以普通的 HTTP 错误失败。
如果模型在流的中途 3 分钟没有发送任何数据,Lovely Router 会以该流格式的错误事件结束这个流:
event: error
data: {"type": "error", "error": {"type": "api_error", "message": "Upstream stopped responding mid-stream"}}渠道在运行中的流里报告的错误,会被替换为同一格式的通用错误事件(对于 Responses API,是类似 {"type": "error", "code": "server_error", "message": "…"} 的 error 事件),因此渠道自己的措辞不会传到你这里。渠道繁忙或过载时,会变为 Anthropic overloaded_error、OpenAI rate_limit_exceeded 或 Gemini RESOURCE_EXHAUSTED,消息为 Upstream capacity for this model is busy. Retry shortly.;其他情况都会变为 api_error(Gemini 为 UNAVAILABLE),消息为 The model provider returned an error. Please retry. 请从头重试请求;已经流式输出的内容会被计费。
重试失败的请求#
Lovely Router 在返回错误之前,已经会把失败的模型请求切换到其他渠道重试。对于它无法消化的情况,你这一侧也要重试:
- 重试
429、500、502、503、504和网络错误。 - 等待
retry-after响应头指定的秒数(如果有)。否则使用指数退避:1、2、4、8 秒,依此类推,最长 30 秒,再加上最多一秒的随机抖动,避免各个客户端同步重试。 - 大约尝试五次后停止,并把错误抛出。
- 不要重试
400、401、403、404、409、413或422,除非你修改了请求。402只有在充值之后才重试。 - 不要盲目重试启动运行的请求。 如果启动工具运行或浏览器运行超时,请先检查
GET /v1/tools/runs,再决定是否启动新的运行。参阅重试与幂等性。
官方 OpenAI 和 Anthropic SDK 已经会以退避方式对 429 和 5xx 重试两次。要更改次数,请在创建客户端时传入 max_retries(Python)或 maxRetries(Node.js)。对于直接发起的 HTTP 调用,可以使用类似下面的辅助函数:
import os
import random
import time
import requests
RETRYABLE = {429, 500, 502, 503, 504}
def backoff(attempt, retry_after=None):
if retry_after:
return float(retry_after)
return min(30, 2 ** (attempt - 1)) + random.random()
def post_with_retry(url, payload, max_attempts=5):
headers = {"Authorization": f"Bearer {os.environ['LOVELY_API_KEY']}"}
for attempt in range(1, max_attempts + 1):
try:
r = requests.post(url, json=payload, headers=headers, timeout=300)
except (requests.ConnectionError, requests.Timeout):
if attempt == max_attempts:
raise
time.sleep(backoff(attempt))
continue
if r.status_code in RETRYABLE and attempt < max_attempts:
time.sleep(backoff(attempt, r.headers.get("retry-after")))
continue
if not r.ok: # other 4xx, or still failing after the last attempt
raise RuntimeError(f"{r.status_code}: {r.text[:500]}")
return r.json()
reply = post_with_retry(
"https://lovelyrouter.com/v1/chat/completions",
{"model": "gpt-6.1-sol", "messages": [{"role": "user", "content": "Hello"}]},
)
print(reply["choices"][0]["message"]["content"])所有错误格式(Anthropic、OpenAI、Gemini 以及 Lovely Router 自己的格式)都有一条写给人看的 error.message。记录日志时,请把它与状态码以及 x-lovely-request-id 响应头一起记录。