OpenAI insufficient_quotaとcredit_balance_exhausted: 再試行が役に立たない理由

OpenAI API は、アカウントがクレジットを使い果たした場合、または使用制限を超えたときにinsufficient_quotaエラーの種類の429を返します。 レート制限と同じ状態コードですが、数秒待っても修正されません。 アクセスは、クレジットの追加、制限の引き上げ、または毎月の期間のリセット後にのみ返されます。 OpenAI では、課金、支出、クォータのエラーを再試行しても API アクセスは復元されません。また、 error.code を調べて特定の原因を見つける必要があると言います。 詳細については、エラー コードをご覧ください。

OpenAI のクォータ エラーの例

これらのエラーはそれぞれ 429を返します。 error.typeは引き続きinsufficient_quotaできるため、どちらを取得したか確認できるように、error.codeを確認してください。

error.code 意味 アクセスが戻る方法
credit_balance_exhausted 組織にプリペイド クレジットが残っていません。 クレジットを追加します。
organization_spend_limit_exceeded 組織は、すべてのプロジェクトで毎月の支出制限に達しました。 上限を引き上げるか削除するか、毎月のリセットを待ってください。
project_spend_limit_exceeded プロジェクトは毎月の支出制限に達しました。 他のプロジェクトは引き続き動作します。 プロジェクトの制限を引き上げるか削除するか、毎月のリセットを待ってください。
organization_usage_limit_exceeded 組織が OpenAI によって割り当てられた月間使用量の上限に達しました。 これは、設定した使用制限とは別です。 承認された上限を高く要求するか、OpenAI サポートにお問い合わせください。

これらを、rate_limit_exceeded や slow_down などの「レート制限に達しました」エラーと比較します。 これらは一時的なものであり、通常は短い待機後の再試行が機能します。 詳細については、「OpenAI の『Rate limit reached』エラー」を参照してください。

OpenAI クォータ エラーを処理する方法

  1. 状態だけでなく、error.codeを読む。 429だけでは、再試行するかどうかはわかりません。 テーブル内の 4 つのコードを "stop" として扱い、レート制限コードを "wait and retry" として扱います。
  2. 再試行を停止する 要求を再度送信せず、再試行ループが API を呼び出し続けないようにします。 誰かが課金の問題を解決するまで、すべての要求は同じように失敗します。
  3. 失敗する可能性がある呼び出しを一時停止します。 1 つのクォータ エラーは、同じ組織またはプロジェクトからの次の要求も失敗します。 それぞれを送信してエラーを待機する代わりに、それらをスキップします。
  4. ユーザーに伝えてください。 現時点では AI 機能が使用できないことを説明し、残りのアプリを動作させ続けます。
  5. 自分用にアラートを設定する コードを高い重大度でログに記録するか、請求担当者を呼び出してください。 修正はコードの外にあるため、誰かが知る必要があります。

OpenAI Python SDK は、既定では、429応答を 2 回再試行します。 何を再試行しても、最終的にコードは課金コードとともに RateLimitError を受け取り、そこで停止します。

import logging

import openai
from openai import OpenAI

client = OpenAI()
logger = logging.getLogger(__name__)

BILLING_CODES = {
    "credit_balance_exhausted",
    "organization_spend_limit_exceeded",
    "project_spend_limit_exceeded",
    "organization_usage_limit_exceeded",
}
billing_error: str | None = None


def ask(prompt: str) -> str:
    global billing_error
    if billing_error:
        raise RuntimeError("AI features are paused until billing is fixed.")
    try:
        response = client.responses.create(model="gpt-4.1", input=prompt)
        return response.output_text
    except openai.RateLimitError as error:
        if error.code in BILLING_CODES:
            billing_error = error.code
            logger.critical("OpenAI billing error: %s", error.code)
        raise

フラグは、アプリが再起動するまで設定されたままです。 アプリが長時間実行される場合は、別の方法でクリアしてください。たとえば、誰かが課金を修正した後の管理者アクションなどです。

アプリが OpenAI クォータ エラーを処理することをテストする方法

開発中にクォータ エラーが表示されることはほとんどありません。 テスト アカウントにクレジットがあり、使用量が少ない。 そのため、クォータの処理をテストする方法によって、ユーザーが見つける前にバグが見つかるかどうかが決まります。

Approach 見つけたもの 見逃したもの
本番環境を待つ 実際の障害 すべては、ユーザーがそれを操作するまで、AI 機能は誰かが気付くまで停止したままです。
テストで API をモックするか、コーディング エージェントにモックを記述させる 停止分岐が実行されるかどうか OpenAI の実際のエラー本文とコード、および SDK の再試行ポリシー。 アプリでは、モックにアクセスするためにテスト専用のスイッチも必要です。
実クレジットを使い切るか、小さな使用制限を設定する 実際の動作 コストがかかり、同じ組織またはプロジェクトを共有している他のすべてのアプリがブロックされます
アプリの実際のトラフィックをインターセプトし、必要に応じてクォータ エラーを返します 実際の URL、実際の SDK と再試行ポリシー、OpenAI 独自のエラー形式 アプリ内では何も変更されないため、コードを独立した状態でテストするわけではありません。 そのために単体テストを取っておいてください。

アプリで試す

開発プロキシ は、アプリの api.openai.com への要求をインターセプトし、OpenAI エラーを返します。一方、アプリは実際の URL を呼び出し続けます。 openai-throttlingプリセットは、レート制限エラーとcredit_balance_exhaustedエラーを混在させます。 insufficient_quota が返され、その型は Retry-After で、429 ヘッダーはないため、再試行する代わりにアプリが停止することを確認できます。

プリセットをダウンロードし、それを使用して開発プロキシを起動します。

devproxy config get openai-throttling
devproxy --config-file "~dataFolder/configs/openai-throttling/.devproxy/devproxyrc.json"

クォータ エラーのみをテストするには、プリセットの openai-errors.json ファイルを編集し、credit_balance_exhausted 応答のみを保持してください。 支出と使用量の制限コードをテストするには、同じ形式と別の codeを持つ応答を追加します。

その後、通常どおりにアプリを実行し、アプリがどのように動作するかを確認します。 開発プロキシをインストールするには、「 開発プロキシの設定」を参照してください。

次のステップ

参照