OpenAI APIの429エラーは、待って再試行すれば直る場合と、待つだけでは直らない場合があります。まずレスポンス本文のエラーコード、メッセージ、レート制限ヘッダー、使用量・請求状態を確認し、「短時間の上限超過」と「利用枠・予算の問題」を切り分けます。
429を受け取った直後に同じリクエストを連打すると、さらに制限へかかりやすくなります。OpenAIの公式ガイドでも、ランダムな待機時間を含む指数バックオフが案内されています。ただし、残高不足や利用上限が原因なら、再試行回数を増やしても成功しません。
この記事では、ログで確認する項目、原因ごとの対処、JavaScriptの再試行関数、同時実行とトークン量を減らす方法を解説します。
情報確認日:2026年7月18日(日本時間)
結論:429の本文とヘッダーを先に確認する
429を受信
↓
本文の code / type / message を確認
├─ rate limit・短時間の上限
│ ├─ Retry-Afterやresetを確認
│ ├─ 指数バックオフ+ジッター
│ └─ 同時実行・入力・出力を削減
│
└─ quota・billing・usage limit
├─ 使用量と請求設定を確認
├─ プロジェクト・組織・キーを確認
└─ 上限変更または利用量を削減
原因が不明
└─ request IDと時刻を添えてサポート情報を確認
「429」というHTTPステータスだけで原因を決めず、エラー本文を確認します。メッセージやコードの表現はAPIや時期によって変わる可能性があるため、文字列の完全一致だけに依存しない設計が必要です。
OpenAI APIで429が起きる主な原因
| 原因 | 特徴 | 主な対処 |
|---|---|---|
| 毎分のリクエスト上限 | 短時間に大量の呼び出し | 待機、キュー、同時実行制御 |
| 毎分のトークン上限 | 長い入力や大きい出力上限が集中 | 入力・出力削減、処理の平準化 |
| 利用枠・予算 | 待っても継続、請求や上限に関する本文 | 使用量、請求設定、利用上限を確認 |
| 組織・プロジェクト違い | 想定と異なる上限や使用量 | キーの所属、プロジェクト、権限を確認 |
| 再試行の集中 | 障害時に全ワーカーが同時再送 | ジッター、最大試行、サーキットブレーカー |
JavaScriptでエラー情報を記録する
本番環境では、APIキーや入力本文を出さずに、ステータス、エラーコード、リクエストID、関連ヘッダーを記録します。
import OpenAI from "openai";
const client = new OpenAI();
try {
const response = await client.responses.create({
model: process.env.OPENAI_MODEL,
input: "短く要約してください。",
});
console.log(response.output_text);
} catch (error) {
if (error instanceof OpenAI.APIError) {
console.error({
status: error.status,
code: error.code,
type: error.type,
requestId: error.request_id,
message: error.message,
retryAfter: error.headers?.get?.("retry-after"),
remainingRequests:
error.headers?.get?.("x-ratelimit-remaining-requests"),
remainingTokens:
error.headers?.get?.("x-ratelimit-remaining-tokens"),
});
}
throw error;
}
ヘッダーは常に同じ形で存在するとは限りません。取得できない場合を考慮し、任意項目として扱います。サポートへ問い合わせる場合は、APIキーではなくリクエストID、発生時刻、モデル、エラー本文を用意します。
指数バックオフとジッターで再試行する
指数バックオフは、失敗するたびに待機時間を増やす方法です。ジッターはランダムな揺らぎで、複数ワーカーが同時に再送する「再試行の波」を分散します。
import OpenAI from "openai";
const sleep = (ms) =>
new Promise((resolve) => setTimeout(resolve, ms));
function isRetryableRateLimit(error) {
if (!(error instanceof OpenAI.APIError)) return false;
if (error.status !== 429) return false;
const code = String(error.code || "").toLowerCase();
const message = String(error.message || "").toLowerCase();
const looksLikeQuotaProblem =
code.includes("quota") ||
message.includes("quota") ||
message.includes("billing");
return !looksLikeQuotaProblem;
}
async function withBackoff(operation, maxAttempts = 5) {
let lastError;
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
try {
return await operation();
} catch (error) {
lastError = error;
if (!isRetryableRateLimit(error) || attempt === maxAttempts) {
throw error;
}
const headerSeconds = Number(
error.headers?.get?.("retry-after")
);
const exponentialMs = 500 * 2 ** (attempt - 1);
const jitterMs = Math.floor(Math.random() * 500);
const waitMs = Number.isFinite(headerSeconds)
? headerSeconds * 1000 + jitterMs
: Math.min(exponentialMs + jitterMs, 30_000);
await sleep(waitMs);
}
}
throw lastError;
}
呼び出し側では、API処理を関数として渡します。
const response = await withBackoff(() =>
client.responses.create({
model: process.env.OPENAI_MODEL,
input: "この文章を3行に要約してください。",
})
);
判定の注意:上の関数は実装例です。エラーコードや本文の表現変更を完全には吸収できません。本番では利用APIの実際のエラーを記録し、OpenAIの最新エラーガイドに合わせて判定を更新してください。
再試行してはいけないケース
- 利用枠、請求、予算上限が原因と判断できる
- APIキーや権限など、待機で直らないエラー
- 利用者が画面を閉じ、処理をキャンセルした
- 期限を過ぎた処理や、結果が不要になった処理
- 副作用があり、重複実行を防げない処理
OpenAIの公式ガイドでは、失敗したリクエストも毎分の制限へ影響するため、連続した即時再送は解決にならないと説明されています。
同時実行数をキューで制御する
100件を一度に Promise.all() へ渡すと、瞬間的に上限へ達しやすくなります。ワーカー数を決めたキューで平準化します。
async function mapWithConcurrency(items, limit, worker) {
const results = new Array(items.length);
let nextIndex = 0;
async function run() {
while (true) {
const index = nextIndex;
nextIndex += 1;
if (index >= items.length) return;
results[index] = await worker(items[index], index);
}
}
const runners = Array.from(
{ length: Math.min(limit, items.length) },
() => run()
);
await Promise.all(runners);
return results;
}
固定の同時実行数だけでなく、残り上限や応答時間を見て速度を調整する方法もあります。複数プロセスや複数サーバーがある場合、各プロセス内だけの制限では全体上限を超えるため、共有キューやレート制御基盤を使います。
トークン上限による429を減らす
- 会話履歴を無制限に再送しない
- 検索結果や文書から必要な部分だけを渡す
- 出力の形式と長さを具体的に指定する
- 大きな処理を時間帯やキューで分散する
- モデルごとの上限と使用量を分けて監視する
長い入力がなぜ増えるのかはコンテキストウィンドウの基本で確認できます。出力上限を極端に大きく設定すると、実際の出力が短くてもレート制限の計算へ影響する場合があるため、必要量に合わせます。
利用枠・請求状態を確認する
待機しても同じ429が続き、本文に利用枠や請求を示す情報がある場合は、Platformの使用量、請求、プロジェクト、組織、利用上限を確認します。
- 正しい組織・プロジェクトを開いているか確認する
- 使用量と予算上限、請求設定を確認する
- APIキーが想定プロジェクトへ属しているか確認する
- モデルごとの利用層や上限を確認する
- 上限変更後は反映状況を確認し、少数のリクエストで再テストする
APIキーをログや問い合わせへ貼らないでください。キーの所属を整理する方法はAI APIキーの安全な管理方法で解説しています。
429対策の監視項目
| 指標 | 分かること |
|---|---|
| 429率 | 処理全体に対して制限がどれだけ起きているか |
| 再試行成功率 | 待機で直る問題か、恒久問題が多いか |
| 入力・出力トークン | リクエスト数以外の上限要因 |
| キュー待ち時間 | 利用者体験と処理能力の不足 |
| モデル・プロジェクト別件数 | 特定上限への偏り |
解決しない場合のチェックリスト
- エラー本文のcode、type、messageを保存した
- リクエストIDと発生時刻を保存した
- 同じ処理の多重起動や無限ループがない
- 全サーバーを合計した同時実行数を確認した
- 正しい組織・プロジェクトの使用量を見ている
- モデルIDとモデル別上限を確認した
- 請求・利用上限の問題を確認した
- SDKと公式エラーガイドの最新版を確認した
よくある質問
何秒待てば429は直りますか?
原因と上限によって異なります。利用可能なら Retry-After やレート制限ヘッダーを参照し、ない場合は上限付きの指数バックオフを使います。利用枠や請求が原因なら待機では解決しません。
再試行回数を増やせば成功率は上がりますか?
無制限に増やすと制限と遅延を悪化させます。最大試行数、全体の期限、ジッターを設定し、失敗後はキューへ戻すか利用者へ再実行を案内します。
429が出たら別のAPIキーへ切り替えてよいですか?
制限回避を目的にキーを切り替える設計は避けます。同じ組織やプロジェクトの上限であれば解決しないこともあります。正しい利用層、上限、処理速度を確認してください。
まとめ
OpenAI APIの429は、ステータスだけでなく本文、ヘッダー、使用量・請求状態を見て切り分けます。短時間の上限には指数バックオフとジッター、同時実行制御、入力・出力削減が有効です。
利用枠や請求が原因なら自動再試行を止め、管理者へ通知します。リクエストIDとメトリクスを記録し、再試行が新たな負荷にならない構成にしてください。