0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

upstream 5xx と自分の設定ミスを切り分ける HTTP ステータス表

0
Posted at

はじめに

OpenAI 互換 API を運用していると、HTTP status だけを見て判断したくなる場面があります。

特に 500 番台を見ると、私は反射的に「upstream が落ちているのでは」と思いがちです。ただ、今回あらためて確認したら、503 でも中身は model_not_found で、自分側の model 指定やルーティング設定を見るべきケースがありました。

この記事では、私が一次切り分けで見る HTTP status、error body、request ID、model、endpoint を表にします。サポートに投げる前の最小再現 curl も残します。

再現環境

今回の確認は 2026-07-06 09:32-09:34 JST に行いました。

項目
endpoint https://router.flatkey.ai/v1/chat/completions
model list GET https://router.flatkey.ai/v1/models
正常系 model gemini-2.5-flash-lite
異常系 model not-a-real-model-issue-193
備考 request ID は公開記事では一部伏せています

/v1/models は HTTP 200 で、見えている model は 47 件でした。正常系の最小 chat は HTTP 200、usage.total_tokens=7 でした。

エラー全文

まず fake key です。これは素直に認証エラーでした。

{
  "http_status": 401,
  "error": {
    "code": "",
    "message": "Invalid token (request id: 20260706003333...redacted)",
    "type": "new_api_error"
  }
}

次に、実在しない model 名を指定したケースです。ここが今回のメモの主題です。HTTP status は 503 ですが、本文の codemodel_not_found でした。

{
  "http_status": 503,
  "error": {
    "code": "model_not_found",
    "message": "分组 company-employees 下模型 not-a-real-model-issue-193 无可用渠道(distributor) (request id: 20260706003333...redacted)",
    "type": "new_api_error"
  }
}

この場合、私は 503 だけを見て retry 連打するより先に、同じ key で /v1/models に出ている model か、route や group が期待通りかを確認した方がよいと思いました。

再現手順

fake key の確認です。実運用では本物の key を貼らないようにします。

curl -sS -i "https://router.flatkey.ai/v1/chat/completions" \
  -H "Authorization: Bearer sk-fk-local-fixture-invalid" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-5.4-mini",
    "messages": [{"role": "user", "content": "ping"}],
    "max_tokens": 1
  }'

同じ key で見えている model を確認します。

curl -sS "https://router.flatkey.ai/v1/models" \
  -H "Authorization: Bearer $FLATKEY_API_KEY" \
  | jq -r '.data[]?.id'

実在しない model を指定します。これは負荷をかけずに model 名のミスを確認するための最小リクエストです。

curl -sS -i "https://router.flatkey.ai/v1/chat/completions" \
  -H "Authorization: Bearer $FLATKEY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "not-a-real-model-issue-193",
    "messages": [{"role": "user", "content": "ping"}],
    "max_tokens": 1
  }'

正常系も 1 回だけ置いておくと、key、base URL、endpoint が全滅しているのか、特定 model だけが悪いのかを分けやすいです。

curl -sS -i "https://router.flatkey.ai/v1/chat/completions" \
  -H "Authorization: Bearer $FLATKEY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-2.5-flash-lite",
    "messages": [{"role": "user", "content": "Reply with ok only."}],
    "max_tokens": 3
  }'

HTTP status だけで見ないための表

私の手元では、まずこの表で「自分の設定を見るもの」と「upstream や混雑を疑うもの」を分けます。

status まず疑うもの retry 判断 集める情報
400 JSON、schema、header、endpoint に合わない parameter そのまま retry しない request body、endpoint、SDK version、validation error
401 API key、organization、project、IP allowlist retry しない key の発行元、環境変数名、認証 header
403 region、権限、利用できない endpoint retry しない account/project 権限、利用地域、endpoint
404 endpoint path、resource ID、model 名 retry しない base URL、path、model、同じ key の /v1/models
408 request timeout 条件付きで retry timeout 設定、処理時間、X-Client-Request-Id
429 rate limit RPM/TPM、並列数、急な traffic 増 backoff と jitter rate-limit headers、並列数、queue 長
429 quota credit、monthly spend、project budget retry しない billing、usage、limit、どの project の key か
500 provider/server 側の処理失敗 短い待ち時間後に上限付き retry status page、request ID、最小再現
502/504 gateway、network、upstream timeout 上限付き retry router request ID、upstream 名、timeout
503 overloaded upstream 混雑、Slow Down backoff、rate を戻してから漸増 traffic 推移、429/503 比率
503 model_not_found model 名、route、group、catalog 差分 retry 連打しない model、同じ key の /v1/models、routing 設定

502/504 は今回わざと起こしていません。実障害を作るのはよくないので、ここは OpenAI 互換 gateway での一般的な local fixture として扱っています。

この表で大事にしているのは、retry できるかどうかを status だけで決めないことです。たとえば 429 は同じ status でも、短時間に投げすぎた rate limit と、残高や月次上限を超えた quota では対応が違います。前者は待つ、並列数を落とす、jitter を入れる、という話になります。後者は billing や project budget を直すまで同じ request を投げても進みません。

5xx も同じです。500 や overloaded の 503 なら、短い待ち時間を置いた上限付き retry と status page の確認が自然です。一方で、今回のように body に model_not_found が入っているなら、upstream 障害というより、自分の model 指定、利用可能 group、routing、catalog の差分を疑う方が早いです。私はここを混ぜて見てしまいがちなので、support に渡す前に body まで読むようにしています。

私の切り分け順

私はだいたい次の順で見ます。

  1. status だけでなく error.codeerror.typeerror.message を見る
  2. x-request-id、body 内の request ID、gateway 固有の request ID を保存する
  3. 同じ key で /v1/models を叩き、指定 model が本当に見えているか確認する
  4. endpoint family を確認する。/v1/chat/completions/v1/responses を混ぜない
  5. 401、403、404、400 は自分の設定ミスとして先に潰す
  6. 429 は rate limit と quota を分ける。quota は retry で直らない
  7. 5xx は body の code を見る。model_not_found のように設定寄りの 5xx もある
  8. 同じ最小 curl で再現するかを確認してからサポートに渡す

OpenAI の rate limit docs でも、失敗した request は per-minute limit に加算されると説明されています。なので、429 や 503 を見た瞬間に無制限 retry するのは、私は避けた方がよいと思っています。

再試行より先に証跡を固定するだけで、あとから原因を追いやすくなります。

サポートに投げる前の最小セット

サポートへ投げる前に、私はこれだけ揃えます。

TRACE_ID="$(uuidgen | tr '[:upper:]' '[:lower:]')"

curl -sS -i "https://router.flatkey.ai/v1/chat/completions" \
  -H "Authorization: Bearer $FLATKEY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-Client-Request-Id: $TRACE_ID" \
  -d '{
    "model": "not-a-real-model-issue-193",
    "messages": [{"role": "user", "content": "ping"}],
    "max_tokens": 1
  }'

共有する項目はこのくらいです。

項目
status 503
request ID 20260706003333...redacted
client request ID $TRACE_ID の値
endpoint /v1/chat/completions
model not-a-real-model-issue-193
body error JSON 全体。key は絶対に含めない
再現性 1 回だけか、複数回か、特定 model だけか

OpenAI API reference では、x-request-id の保存と、必要に応じて X-Client-Request-Id を付ける方法が案内されています。timeout や network error で response header が取れないときも、自分で付けた client request ID があると調査しやすくなります。

気づき

今回一番の反省は、503 を見てすぐ upstream 障害と決めないことでした。

もちろん 500 や overloaded 系の 503 は provider 側の一時失敗として扱うことがあります。ただ、同じ 503 でも body が model_not_found なら、私の model 名、catalog、route、group 設定を見る方が先です。

逆に 401、403、404、400 は、たいてい自分の設定を直さないと進みません。retry よりも、key、base URL、endpoint、model、project 権限を紙に書くくらいの気持ちで揃えた方が早いかもしれません。

参考

おわりに

HTTP status は入口としては便利ですが、OpenAI 互換 API では gateway、model catalog、upstream provider、quota、rate limit が重なります。

私もしばらく 5xx なら upstream と雑に考えていたところがあるので、これからは status、request ID、model、endpoint、最小再現 curl を先に揃えてから判断しようと思います。

間違いあったらコメントください。よろしくお願いします。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?