マガジン

LLM APIの429エラーを切り分ける:レート制限・残高不足・混雑の見分け方と待ち方

AIを使いこなす

Claudeで執筆し、GPTで自動校閲・修正しています。

砂時計のそばで豆を三つの皿に仕分ける手元
記事の内容をもとに制作したAI生成イメージです。実際の製品画面や検証結果の写真ではありません。

LLM APIの429は「今は受け付けられない」という合図ですが、原因は一つではありません。待てば直るもの(短時間の送りすぎ、急な増加)と、待っても直らないもの(残高ゼロ、支出上限、月間上限)が同じ429で返ってきます。 見分ける材料は、ステータスコードではなく、エラー本文のコード名と Retry-After ヘッダーの有無です。 結論を先に書くと、次の順で判定します。 1. 本文のコード名が残高・支出上限・利用上限系なら、リトライせず人間(または課金・上限設定)に回す。 2. そうでなく Retry-After があれば、その秒数以上待つ。 3. どちらでもなければ、指数バックオフ+ジッターで回数と総時間に上限をつけて再試行する。 「混雑」は、OpenAIでは503、Anthropicでは529として返るのが公式の整理です。429の中身は主に「あなたの側の使い方」か「アカウントの枠」なので、429と混雑は分けて扱います。 本記事の内容は2026年10月27日に各社の公式ドキュメントを開いて確認した範囲です。コード名や上限は更新されることがあるため、実装前に最新版を見直してください。

この記事の目次
  1. 最初に見る3か所:ステータス・本文・ヘッダー
  2. 原因別の対処表
  3. 判定とバックオフの擬似コード
  4. つまずきやすい4つの落とし穴
  5. 復旧後に人が確認すること

最初に見る3か所:ステータス・本文・ヘッダー

429を受けたら、最低限この3つをログに残します。

  • ステータスコードと error.type:Anthropicは429を rate_limit_error として返します。
  • 本文のコード名とメッセージ:残高不足や上限超過はここで区別されます。
  • retry-after と、リクエストID:Anthropicは本文の request_id とヘッダーの request-id でIDを返します。サポートに問い合わせるときに必要です。

重要なのは、Anthropicでは月間の支出上限に達したときも rate_limit_error の429になる点です。このときは retry-after がなく、error.details.error_code が enforced_spend_limit_reached になると Anthropicのレート制限ページ に記載されています。型名だけで判定すると、レート制限と取り違えます。

原因別の対処表

公式ドキュメントに記載のあるコード名・挙動を、見分け方と対処にまとめました。待ち時間は各社の記述に従い、ここでは具体的な秒数は載せていません。

  • OpenAI、見分ける手がかり:429「Rate limit reached for requests」、待てば直る?:直る、次の一手:Retry-After に従い、送信ペースを落とす
  • OpenAI、見分ける手がかり:429 slow_down(リクエスト増加が急)、待てば直る?:直る、次の一手:送信量を下げ、段階的に戻す
  • OpenAI、見分ける手がかり:429 credit_balance_exhausted、待てば直る?:直らない、次の一手:クレジットを追加する
  • OpenAI、見分ける手がかり:429 organization_spend_limit_exceeded / project_spend_limit_exceeded、待てば直る?:直らない、次の一手:組織またはプロジェクトの支出上限を見直す
  • OpenAI、見分ける手がかり:429 organization_usage_limit_exceeded、待てば直る?:直らない、次の一手:上限の引き上げ申請かサポートへの連絡
  • OpenAI、見分ける手がかり:503 server_is_overloaded、待てば直る?:直る(混雑)、次の一手:Retry-After があれば従って再試行
  • Anthropic、見分ける手がかり:429 rate_limit_error + retry-after あり、待てば直る?:直る、次の一手:RPM・入力トークン・出力トークンのどれかを超過。秒数待つ
  • Anthropic、見分ける手がかり:429 + enforced_spend_limit_reached、retry-after なし、待てば直る?:直らない、次の一手:階層の月間上限。翌月1日0:00 UTCまで停止するか、上限引き上げを依頼
  • Anthropic、見分ける手がかり:利用量の急増による429(acceleration limits)、待てば直る?:直る、次の一手:増やし方を緩やかにし、利用パターンを安定させる
  • Anthropic、見分ける手がかり:529 overloaded_error、待てば直る?:直る(混雑)、次の一手:バックオフで再試行
  • Anthropic、見分ける手がかり:自分で設定した支出上限は400 invalid_request_error、待てば直る?:直らない、次の一手:429ではない点に注意。上限を上げるか外す
  • Anthropic、見分ける手がかり:402 billing_error、待てば直る?:直らない、次の一手:支払い情報を確認する
  • Gemini、見分ける手がかり:429 RESOURCE_EXHAUSTED、待てば直る?:内容による、次の一手:RPM・TPMなら待つ。1日あたりの上限(RPD)なら翌日(太平洋時間の午前0時リセット)か枠の引き上げ

出典:OpenAI エラーコード、OpenAI レート制限、Anthropic エラー、Anthropic レート制限、Gemini API レート制限。

Geminiの制限は、APIキー単位ではなくプロジェクト単位で適用されます。同じプロジェクトの別サービスが枠を使っていると、自分のコードに問題がなくても429になります。

判定とバックオフの擬似コード

以下は説明用の擬似コードで、実行・検証はしていません。提供元ごとの本文の構造が違うため、extract_error_code は自分の環境で実際のレスポンスを見て実装してください。OpenAIの課金関連エラーは、公式のエラーコードページに従い error.code から取り出します。error.type は insufficient_quota の場合もあるため、型名だけでは原因を区別できません。待ち時間の初期値(1秒、上限60秒、5回、90秒)は編集上の出発点であり、公式の推奨値ではありません。

STOP_CODES = {
  "credit_balance_exhausted", "organization_spend_limit_exceeded",
  "project_spend_limit_exceeded", "organization_usage_limit_exceeded",
  "enforced_spend_limit_reached"
}
BASE = 1.0        # 秒
CAP = 60.0        # 1回の待ちの上限
MAX_ATTEMPTS = 5
DEADLINE = 90.0   # 呼び出し全体で許す秒数

function classify(resp):
  code = extract_error_code(resp.body)   # 提供元ごとに取り出し位置が違う
  if code in STOP_CODES:
    return "STOP_BILLING"                # 待っても直らない
  if resp.status in (429, 503, 529):
    return "RETRY"
  return "STOP_OTHER"

function call_with_retry(send):
  start = now()
  for attempt in 0 .. MAX_ATTEMPTS - 1:
    resp = send()
    if resp.ok: return resp
    if classify(resp) != "RETRY":
      raise Fatal(resp.status, request_id(resp))

    ra = header(resp, "retry-after")     # 秒。なければ null
    if ra != null:
      wait = float(ra) + random(0, 1.0)  # 指示より早く戻らない
    else:
      ceiling = min(CAP, BASE * 2 ** attempt)
      wait = ceiling / 2 + random(0, ceiling / 2)   # ジッター付き

    if now() - start + wait > DEADLINE:
      raise GiveUp(resp.status, request_id(resp))
    sleep(wait)
  raise GiveUp("max attempts")

ジッターを入れる理由は、複数のクライアントが同じタイミングで再試行して衝突するのを避けるためで、OpenAIのレート制限ガイドにも同趣旨の説明があります。ここでは待ち時間の半分を固定、残り半分をランダムにしています。完全なランダムだと、初回の再試行でほぼ待たない可能性があるためです。

つまずきやすい4つの落とし穴

1. 失敗した再送も枠を消費する。 OpenAIは、失敗したリクエストも1分あたりの制限に含まれるため、同じリクエストを連続で送り直しても解決しないと説明しています。バックオフに加えて、同時実行数を絞るキューをクライアント側に置くと、再試行の嵐を防げます。

2. SDKの自動リトライと二重になる。 AnthropicのSDKは、接続エラー・レート制限・5xxを既定で2回、指数バックオフで自動再試行し、retry-after があれば従います。自前でループを巻くと、実際の試行回数が掛け算になります。どちらか一方に寄せ、SDK側なら max_retries を調整します。なお、支出上限の429では retry-after がないため、SDKの自動再試行も失敗し続けます。

3. 「残高不足」を再試行し続ける。 上の表で「直らない」とした行は、再試行するほどログとアラートが増えるだけです。STOP_CODESに当たったら、再試行を止めて課金・上限設定の担当者へ通知します。

4. 急に流量を増やす。 OpenAIの slow_down も、Anthropicのacceleration limitsも、増え方が急なときに出ます。バッチ処理を始めるときは、最初から全力で流さず、段階的に上げます。OpenAIのドキュメントでは、毎分100万入力トークンに達したら、15分ごとの増加を50%以内に抑えることが目安とされています。適用される境界はモデルやトラフィックの状況によって変わります。

復旧後に人が確認すること

自動で待てる429と、人が動くべき429を分けたら、運用側で次を確認します。

  • STOP系のコードが出たとき、通知が誰に届くか(残高・上限は開発者ではなく管理者の権限であることが多いです)。
  • ログに、ステータス・コード名・retry-afterの有無・リクエストIDが残っているか。キーや利用者の入力そのものは残さないでください。
  • 自分で設定した月間上限が、本番トラフィックの想定より低くないか。
  • Geminiなら、同じプロジェクトを共有する他のワークロードの利用量。

429が出たとき、まずコード名を見る。これだけで「待つ」「止める」「人を呼ぶ」の分岐がほぼ決まります。

出典・参考資料