対処できるエラー

· Hyperouter · 読了目安 6 分

Hyperouter のエラーはすべて、OpenAI のエラーオブジェクトと、対応する HTTP ステータスで返されます。OpenAI のエラーを処理するコードであれば、そのほとんどをすでに処理できます。このガイドでは、対処すべきものとそうでないものを整理し、最後にリトライのループを紹介します。

エラーオブジェクト

{
  "error": {
    "message": "n must be an integer from 1 to 128",
    "type": "invalid_request_error",
    "code": "invalid_body",
    "param": "n"
  }
}
Field意味
message何が問題かを説明する文です。解析しないでください。
typeエラーの種類です。
code原因を示す安定した識別子です。このフィールドで判定してください。
param問題のあるリクエストのフィールド、または null です。

一部のエラーには generation_id が加わります。これは、まだ実行中、またはすでに実行されたジョブの ID です。GET /v1/generations/{id} でポーリングしてください。

対処すべきステータス

ステータス意味対処
400リクエストが無効です。code が原因を、param が該当のフィールドを示します。リクエストを修正してください。そのままでは再試行しないでください。
401API キーがない、または有効ではありません。キーを確認してください。
402insufficient_credits:残高またはキーの上限が、リクエストにかかりうる最大額をまかなえません。チャージするか、キーの上限を引き上げてください。
403アカウントが停止されている、または機能やモデルがアカウントで有効になっていません。サポートチケットを作成してください。
404そのような ID がない、他のアカウントの ID、または expires_at を過ぎた動画です。再試行しないでください。
409呼び出しを許可する状態にない、または Idempotency-Key が競合しています。Idempotency-Key で安全にリトライするを参照してください。
429すべてのプロバイダーが上限に達している、またはアカウントがレート制限を超えています。Retry-After の時間だけ待ってから、再試行してください。
500、501Hyperouter が失敗した、またはエンドポイントが実装されていません。課金されません。500 は、下記のとおり注意して再試行してください。
503プロバイダーが失敗した、または時間内に応答しませんでした。下記のとおり再試行してください。

よく遭遇する 3 つのコード

同じ系統に venue_busy(429)があります。チャットモデルのすべてのプロバイダーが、レートの上限に達している状態です。

502 や 504 ではなく 503 を返す理由

Hyperouter は 502 や 504 を返しません。これらは、エラーボディのない、エッジネットワークからの素のページとして届いてしまい、code を読み取れないためです。

ゲートウェイであればこれらを返す場面では、通常のエラーオブジェクトを持つ 503 が返り、ゲートウェイのステータスはレスポンスヘッダー X-Upstream-Status に入ります。プロバイダーが失敗した場合は 502、タイムアウトした場合は 504 です。どの種類の失敗かは code が示し、all_venues_failed、upstream_error、timeout のいずれかです。

HTTP/2 503
x-upstream-status: 504

失敗とタイムアウトを区別したい場合は、X-Upstream-Status を読み取ってください。ほとんどのコードでは、503 と code で十分です。

再試行してはいけない場合

再試行が常に安全とは限りません。再試行によって、2 つ目のジョブや 2 回目の課金が発生することがあります。Hyperouter は、そのようなレスポンスに x-should-retry: false を付けます。

チャットでは、リクエストを受け付けたプロバイダーが、それを実行中である可能性があります。その後プロバイダーが応答しなくなった場合、リクエストは別のプロバイダーには送信されません。コード timeout または upstream_error の 503 が返り、確保した額が課金されます。再送するかどうかを決める前に、GET /v1/generations/{id} で調べてください。

バックオフ付きのリトライのループ

429 と 503 を再試行し、Retry-After に従い、x-should-retry: false の場合は諦め、料金がかかるリクエストには Idempotency-Key を付けます。

import random
import time
import uuid

import requests

def post_with_retry(url, headers, body, attempts=5):
    headers = {**headers, "Idempotency-Key": str(uuid.uuid4())}  # same key on every attempt
    for attempt in range(attempts):
        r = requests.post(url, headers=headers, json=body, timeout=120)
        if r.status_code < 400:
            return r.json()
        if r.headers.get("x-should-retry") == "false":
            r.raise_for_status()
        if r.status_code not in (429, 503) or attempt == attempts - 1:
            r.raise_for_status()
        wait = float(r.headers.get("Retry-After", 2 ** attempt))
        time.sleep(wait + random.random())  # jitter

チャットのリクエストでは、最初の試行が実際に実行されていた場合、再試行に対して 409 idempotency_key_replayed が返ります。これは、GET /v1/generations/{id} で記録を読み取り、再試行をやめる合図です。

OpenAI SDK は、408、409、429、5xx をすでに 2 回再試行し、x-should-retry: false にも従うため、ループが不要な場合もあります。

次のステップ