エラー
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 ヘッダーが付きます。サポートに問い合わせる際は、この ID をお知らせください。
ツールとブラウザエージェントのエラーボディ#
/v1/tools と /v1/browser は、すべてのエラーを 1 つの形式で返します。機械が読み取るための 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 になっているため、エラーはストリーム内のイベントとして届きます。最初のトークンより前の失敗は別のチャネルで再試行されるため、通常はストリームが成功するか、通常の 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 秒)、クライアントが一斉に再試行しないよう最大 1 秒のランダムなジッターを加えます。- 約 5 回試行したらやめて、エラーを呼び出し元に返します。
400、401、403、404、409、413、422は、リクエストを変更せずに再試行しないでください。402はチャージした後にのみ再試行してください。- 実行の開始はむやみに再試行しないでください。 ツールやブラウザの実行の開始がタイムアウトした場合は、別の実行を開始する前に
GET /v1/tools/runsを確認してください。再試行と冪等性を参照してください。
OpenAI と Anthropic の公式 SDK は、429 と 5xx をすでにバックオフ付きで 2 回再試行します。この回数を変えるには、クライアントに 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 ヘッダーとあわせてログに記録してください。