本文へ移動
AI開発 AI生成 文責 blackstrawberry

AI Gateway の資格情報拒否は401・コード2009に、Unified Billing は503

AI Gateway の POST /ai/run で、プロバイダが API キーを拒否したときの応答が変わった。Vertex と Unified Billing を含む新旧ステータスと、エラー処理で直す箇所を整理する。

HTTP 401 プロバイダが API キーを拒否したときの新しい応答(エラーコード 2009) POST /ai/run が対象。Unified Billing 利用時のみ HTTP 503(2026年10月6日付 changelog)

Cloudflare AI Gateway の REST API で、AI プロバイダが資格情報を拒否したときの応答が揃った。対象は POST /ai/run だ。2026年10月6日付の changelog によると、ElevenLabs、Google Vertex、その他のプロバイダは、いずれも HTTP 401 とエラーコード 2009 を返すようになった。例外は Unified Billing を使っている場合で、こちらは HTTP 503 になる。

直す必要があるのは、ステータスコードでプロバイダ鍵の失敗を判定しているアプリだ。ElevenLabs の 403、Vertex の 500、その他のプロバイダの 402 を「鍵の問題」として拾っていた分岐は、変更後はどれにも当たらない。changelog も、REST API のエラーを扱うアプリは HTTP 401 を「無効または拒否されたプロバイダ資格情報」として扱うよう更新すべきだと書いている。

プロバイダごとの新旧レスポンス

状況以前の応答新しい応答
ElevenLabsプロバイダ固有の UserCredentialsError(HTTP 403)HTTP 401、エラーコード 2009
Google Vertex資格情報拒否で HTTP 500、上流への再試行ありHTTP 401、エラーコード 2009。プロバイダへの再試行なしで失敗
その他すべてのプロバイダHTTP 402 またはプロバイダ固有のステータスHTTP 401、エラーコード 2009
Unified Billing 利用時にプロバイダが資格情報を拒否プロバイダ固有の認証エラーHTTP 503

出典:Cloudflare Changelog「Standardize provider credential error responses in AI Gateway」(2026年10月6日)

上の三行は 401 に収束した。プロバイダごとにばらばらだった 403・500・402 を個別に覚えておく必要はなくなる。ただし最後の行だけは 401 にならない。この非対称が、エラー処理を直すときのいちばんの落とし穴になる。

Vertex の鍵エラーは 5xx から外れる

以前の Vertex は、資格情報が拒否されても HTTP 500 を返し、しかも AI Gateway が上流への再試行をかけていた。鍵が間違っているだけなのに、アプリからはサーバー側の障害に見えていたことになる。

変更後は 401 とエラーコード 2009 が返り、リクエストはプロバイダへ再試行せずに失敗する。5xx を一時障害とみなして再試行する実装なら、Vertex の鍵エラーはその再試行の対象から外れる。エラー率を 5xx で監視している場合も、鍵の誤りが原因だった 500 は 4xx 側に数えられるようになる。Vertex を使っていて 500 の件数をアラートの閾値にしているなら、変更前後で数字の意味が変わる点は押さえておきたい。

Unified Billing では 401 にならない

Unified Billing を使っているときにプロバイダが資格情報を拒否すると、新しい応答は HTTP 503 だ。以前はプロバイダ固有の認証エラーが返っていた。

503 は一般に「一時的に使えない」という意味で扱われ、指数バックオフ付きの再試行対象に入れている実装は多い。そうした実装では、Unified Billing 経由の資格情報拒否も再試行のループに入る。changelog の表には、この 503 にエラーコード 2009 が付くかどうかは書かれていない。ほかの理由による 503 とどう見分けるかも、表からは読み取れない。Unified Billing と自前の鍵(BYOK)を併用しているアプリは、同じ「鍵の拒否」が経路によって 401 と 503 に分かれることになる。AI Gateway の請求まわりの変更は 月次請求の集約の記事 で扱った。

エラー処理を直す順番

既存のハンドラを次の順に見直すと漏れが少ない。

  1. 403・402・500 でプロバイダ鍵の失敗を判定している分岐と、UserCredentialsError という名前で分岐している箇所を探す。
  2. HTTP 401 を「プロバイダ資格情報が無効または拒否された」として扱う分岐を加え、鍵の更新や設定確認に回す。
  3. エラーコード 2009 で絞り込みたい場合は、実際のレスポンスでコードがどこに入るかを確かめてから条件を書く。changelog の表はコードの値だけを示している。
  4. Unified Billing を使っているなら、503 の再試行回数と上限を見直す。
  5. Vertex の 5xx を監視している場合は、閾値とダッシュボードの前提を更新する。

ステータスだけで分ける最小の形は次のようになる。レスポンス本文の構造は changelog に載っていないので、ここでは触れていない。

const res = await fetch(gatewayUrl, { method: "POST", headers, body });

if (res.status === 401) {
  // Provider rejected the credential (error code 2009 per the changelog)
  throw new ProviderCredentialError(await res.text());
}

if (res.status === 503 && usesUnifiedBilling) {
  // With Unified Billing, a rejected credential now surfaces as 503
  // Keep retries bounded so a bad credential does not loop forever
}

changelog に書かれていないこと

対象として明記されているのは POST /ai/run だけだ。それ以外のエンドポイントで同じ変更が入ったかどうかは、changelog からは分からない。段階的な展開か一斉適用か、適用の時刻も書かれていない。401 のレスポンス本文の形式と、Unified Billing の 503 を他の 503 と見分ける手がかりも示されていない。ハンドラを書き換える前に、ステージング環境でわざと無効な鍵を送り、実際の本文を一度見ておくと安全だ。

出典 種別について