OpenAI互換APIのトラブルシューティングは、失敗したリクエストをすべて「プロバイダーがダウンしている」と扱うのをやめるだけで、ずっと簡単になります。移行の失敗の多くは、キー、ベースURL、エンドポイントの種類、モデル名、ストリーミング動作、または課金/読み戻しという6つの層のいずれかに起因します。
Flatkeyは、モデルへのアクセス、ルーティング、課金、使用状況分析、運用制御を一か所にまとめるのに役立ちますが、OpenAI互換クライアントでも正確な設定は必要です。SDK上では正しく見えるリクエストでも、クライアントが誤った/v1ルートを向いていたり、モデルエイリアスが別のエンドポイント種別に属していたり、ストリームがプロキシでバッファリングされていたりすると失敗することがあります。
アプリケーションコードを変更する前に、このOpenAI互換APIトラブルシューティングガイドをクリーンなデバッグ手順として使ってください。curlから始め、非ストリーミングのリクエストを1つ通し、次にSDKを追加し、その後にストリーミング、ツール、本番トラフィックを一度に1層ずつ追加します。
5分でできるOpenAI互換APIトラブルシューティング手順
フレームワークのコードを確認する前に、動作するはずの最小リクエストを取得します。Flatkeyでは、現在のコンソールに表示されているベースURLを使用してください。Flatkeyの公開ホームページには現在https://router.flatkey.ai/v1/chat/completionsへのリクエストが表示されており、これはSDKクライアントが通常、/v1ルートをベースURLとして受け取り、SDKが/chat/completionsを追加する必要があることを意味します。
export FLATKEY_API_KEY="sk-fk-..."
export FLATKEY_BASE_URL="https://router.flatkey.ai/v1"
export FLATKEY_MODEL="your-model-alias"
curl -sS "$FLATKEY_BASE_URL/chat/completions" \
-H "Authorization: Bearer $FLATKEY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "'"$FLATKEY_MODEL"'",
"messages": [
{"role": "user", "content": "正確に次を返答してください: ok"}
]
}'
このリクエストが失敗する場合、問題はアプリのフレームワークではありません。まずキー、ベースURL、エンドポイント種別、またはモデルエイリアスを修正してください。成功したら、同じ値をSDKにコピーして、そこからデバッグを続けます。
最速のOpenAI互換APIトラブルシューティングの原則はシンプルです。プレーンな非ストリーミングのテキストリクエストが成功するまでは、ストリーミング、ツール、JSONモード、リトライ、完全なエージェントワークフローをテストしないでください。
エラーは結論ではなく、層として読む
次に何を変更すべきかを判断するために、ステータスコードを使います。
| 症状 | 考えられる層 | 最初に確認すること |
|---|---|---|
401、invalid_api_key、または認証エラー |
キーと認証ヘッダー | Bearer形式、キーの出所、コピー時の余分な空白、プロバイダーキーかゲートウェイキーか |
403または権限拒否 |
アカウント、プロジェクト、またはポリシー | IP許可リスト、プロジェクトメンバーシップ、モデル承認、エンドポイント権限 |
404、model_not_found、または不明なモデル |
モデルカタログとエンドポイント種別 | 正確なモデルエイリアス、モデルの有効化状態、/chat/completionsか/responsesか、または別のエンドポイントか |
400 形式不正のリクエスト |
ペイロードの形 | 必須フィールド、未対応パラメータ、ツールスキーマ、メッセージ形式 |
| ストリームは接続するがトークンが表示されない | ストリーミング経路 | stream: true、SSEパーサー、バッファリングするプロキシ、エンドポイントのストリーム対応 |
| リクエストは成功するが使用状況が欠けている | 読み戻しと課金 | 非ストリーミングの比較リクエスト、ダッシュボード記録、最終ストリームイベントの挙動 |
429、500、502、503、または504 |
レート、容量、または上流 | バックオフ、リクエスト量、ステータスページ、リトライポリシー、フォールバック経路 |
OpenAI自身のエラーガイドでは、401は認証問題、429はレートまたはクォータの問題、500/503応答は再試行可能なサーバーまたは過負荷状態として扱われています。OpenAI互換ゲートウェイは独自の詳細を追加することがあるため、エスカレーション時にはレスポンス本文とリクエストIDを保存してください。
モデルを変更する前に401を修正する
401は、モデルやルートの問題のように見える一方で、実際には認証の問題であることが多いため、OpenAI互換APIトラブルシューティングで最もよくある寄り道です。
次の順で確認してください:
- リクエストに
Authorization: Bearer ...ヘッダーがちょうど1つだけある。 - Flatkeyを呼び出すときは、キーがFlatkeyのキーであり、OpenAI、Anthropic、Google、またはテスト用の直接キーではない。
- キーに、コピーされた引用符、改行、見えないプレフィックス、末尾の空白が含まれていない。
- キーが、シェルだけでなく、実際にプロセスが動作している環境から読み込まれている。
- アカウント、プロジェクト、チーム、またはIPポリシーがそのルートを許可している。
キーを表示しない短いシェルチェックを使ってください:
test -n "$FLATKEY_API_KEY" && echo "key is set"
printf '%s' "$FLATKEY_API_KEY" | wc -c
curlは動作するのにSDKが401を返す場合は、環境変数名を確認してください。OpenAIのPythonクライアントはデフォルトでOPENAI_API_KEYを読み取り、NodeクライアントもデフォルトでOPENAI_API_KEYを読み取ります。アプリが古い直接プロバイダーのキーを持つOPENAI_API_KEYをまだエクスポートしている場合、api_keyまたはapiKeyを明示的に渡さない限り、SDKは新しいゲートウェイキーを無視する可能性があります。
エンドポイントを重複させずにベースURLを修正する
ベースURLのミスは、通常2つのパターンに分かれます:
- SDK が
https://router.flatkey.ai/v1/chat/completionsのような完全なエンドポイントを受け取り、その後/chat/completionsを再度付加してしまう。 - SDK が
https://router.flatkey.aiのようにドメインだけを受け取り、OpenAI 互換の/v1ルートに一度も到達しない。
Python では、base_url を渡すか OPENAI_BASE_URL を設定してください。公式の Python クライアントのソースでも、カスタムの base URL が指定されない場合は https://api.openai.com/v1 にフォールバックします。
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["FLATKEY_API_KEY"],
base_url=os.environ.get("FLATKEY_BASE_URL", "https://router.flatkey.ai/v1"),
)
response = client.chat.completions.create(
model=os.environ["FLATKEY_MODEL"],
messages=[{"role": "user", "content": "Reply with exactly: ok"}],
)
print(response.choices[0].message.content)
Node では、baseURL を渡すか OPENAI_BASE_URL を設定してください。公式の Node クライアントでは、baseURL がデフォルトの OpenAI API ルートを上書きする設定として文書化されています。
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.FLATKEY_API_KEY,
baseURL: process.env.FLATKEY_BASE_URL ?? "https://router.flatkey.ai/v1",
});
const response = await client.chat.completions.create({
model: process.env.FLATKEY_MODEL!,
messages: [{ role: "user", content: "Reply with exactly: ok" }],
});
console.log(response.choices[0]?.message?.content);
この OpenAI 互換 API のトラブルシューティング手順でもまだ失敗する場合は、プロセス起動時に解決された base URL をログに出してください。キーはログに出さないでください。
モデル名をエンドポイントファミリーと分けて考える
「モデルが見つからない」は、エイリアスが間違っていることを意味する場合もありますが、別のエンドポイントファミリーにそのエイリアスが送られていることを意味する場合もあります。チャット補完では動くモデルでも、同じペイロード形状では Responses、Messages、画像、動画、埋め込み経由では公開されていないことがあります。
本番でモデル名を変更する前に、次のチェックリストを実行してください:
| 確認事項 | 重要な理由 |
|---|---|
| 現在の Flatkey コンソールで正確なモデルエイリアスを確認する | ゲートウェイのエイリアスは、プロバイダー直指定のマーケティング名と異なる場合がある |
| エンドポイントファミリーを確認する | /v1/chat/completions と /v1/responses ではリクエスト形状が異なる |
| 任意のパラメータを削除する | 未対応オプションがあると、実際のモデル問題が隠れてしまうことがある |
| 短い非ストリーミングリクエストを試す | 通常リクエストなら、ルートとストリーム解析を切り分けられる |
| 失敗した本文とタイムスタンプを記録する | サポートや監査レビューには、正確なモデル、ルート、エラーが必要 |
OpenAI の外部モデルドキュメントでも、カスタムエンドポイント向けに同じ考え方が使われています。エンドポイント URL を指定し、モデル slug を指定し、検証呼び出しを実行します。ゲートウェイの設定も同じように扱ってください。すべてのサービスに生のモデル文字列を渡させるのではなく、許可済みモデルの小さなマップをコード内に保持しましょう。
非ストリーミングが動作してからストリーミングをデバッグする
ストリーミングは第 2 段階のテストにすべきです。OpenAI Chat Completions のリファレンスでは、JSON の chat completion オブジェクト、または chat completion chunk オブジェクトのストリーミングシーケンスのいずれかが返されます。Responses API も、stream が有効な場合は text/event-stream をサポートします。
直接ストリームを確認します:
curl -N "$FLATKEY_BASE_URL/chat/completions" \
-H "Authorization: Bearer $FLATKEY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "'"$FLATKEY_MODEL"'",
"stream": true,
"messages": [
{"role": "user", "content": "Count from one to five slowly."}
]
}'
非ストリーミングのリクエストが成功してストリームだけ失敗する場合は、ストリームの経路を確認してください:
- レスポンスが SSE 互換の content type を返していることを確認する。
- API クライアントのミドルウェアで、返却前にレスポンス全体をバッファリングしているものを無効にする。
- このルートで reverse proxy のバッファリングを無効にする。
- フロントエンドのパーサーが Chat Completions の chunk を期待しているのに、ルートが Responses イベントを返していないか確認する。
/blog/openai-compatible-streaming-sse-testにある既存の Flatkey ストリーミングチェックリストと比較する。
この OpenAI 互換 API のトラブルシューティング手順は、サーバーレスや自動化ツールで特に重要です。ラッパーによっては HTTP ステータスは成功でも、ストリームが閉じるまでトークンが呼び出し元に届いていない事実を隠してしまうことがあります。
ベースリクエストが正常になってからツールを追加する
ツール呼び出しは、さらに別の失敗層を追加します。ゲートウェイ、ルート、または選択したモデルが、通常のチャットメッセージは受け付けても、ツールスキーマ、tool_choice、並列ツール呼び出し、または厳密な構造化出力設定を拒否することがあります。
次の 3 段階のリクエストで進めてください:
- 同じモデルでの通常のテキストリクエスト。
- 1 つの小さな関数スキーマを追加した同じリクエスト。
- 本番用の完全なツールスキーマ。
1 が成功して 2 が失敗するなら、もはや auth や base URL のデバッグではありません。モデルの機能、エンドポイントファミリー、またはスキーマ対応のデバッグです。任意フィールドを削除し、説明を短くし、選択したモデルルートが必要なツール動作をサポートしているか確認してください。
利用量と請求の読み戻しを証明する
OpenAI互換APIのトラブルシューティングを「レスポンスがテキストを返した」で終わらせてはいけません。本番移行では、財務チームと運用チームが確認する場所で、そのリクエストが見えることも証明する必要があります。
スモークテストが成功したら、次を記録してください。
| 証跡 | それが証明すること |
|---|---|
| リクエストのタイムスタンプとルート | どのゲートウェイ経路がトラフィックを受けたか |
| モデルエイリアス | どの設定済みモデルが要求されたか |
| レスポンスのステータスとリクエストID | サポートが追跡できる内容 |
| usageオブジェクトまたはトークン数 | アプリがコスト要因を記録できるかどうか |
| ダッシュボードまたは請求の読み戻し | 財務が支出を照合できるかどうか |
| フォールバックまたはリトライイベント(ある場合) | ルーティングポリシーが経路を変更したかどうか |
Flatkeyは、1つのキー、明確な価格設定、統合請求、そしてキー・使用量・ルーティングのためのダッシュボードを中心に位置づけられています。移行時には、実トラフィックを流す前に、エンジニアリングのスモークテストとコンソールでの使用量読み戻しチェックを組み合わせてください。
本番対応の安全なトラブルシューティングワークフロー
OpenAI互換APIの移行が失敗しているときは、次の順序で進めてください。
- 現在のコンソールのベースURL、1つのキー、承認済みのモデルエイリアスを使って、ストリーミングなしのcurlリクエストを1回実行する。
- ペイロードを変更する前に、401または403を修正する。
- SDKのバージョンを変更する前に、ベースURLの組み立てを修正する。
- リトライポリシーを変更する前に、モデルエイリアスとエンドポイントファミリーを修正する。
api_keyまたはapiKeyとbase_urlまたはbaseURLを明示してSDKを追加する。- ストリーミングを追加し、クライアントが増分イベントを受信することを確認する。
- ツールまたは構造化出力は、一度に1機能ずつ追加する。
- 使用量と請求の読み戻しを確認する。
- 動作している値をロールバック対応の設定に移す。
この順序により、OpenAI互換APIのトラブルシューティングが当て推量の作業になるのを防げます。各ステップは、レイヤーを証明するか、修正すべきより小さな失敗を示します。
Flatkeyが役立つ場面
Flatkeyは、問題の根本が運用の肥大化にある場合に役立ちます。つまり、プロバイダーキーが多すぎる、モデルアクセスが一貫していない、使用量をレビューしにくい、請求経路が分かれている、といった状況です。統合ゲートウェイは、エンドポイントファミリー、モデルエイリアス、ストリーミング、ツール、請求の読み戻しをテストする必要をなくすものではありませんが、それらのチェックを標準化するための1か所をチームに提供します。
アプリを移行している場合は、このガイドをFlatkeyのOpenAI互換移行ガイド /blog/openai-compatible-api-migration およびスモークテストのチェックリスト /blog/ai-api-smoke-test-checklist と組み合わせてください。
Flatkeyのキーでワークフローをテストする準備ができたら、/sign-up から始め、最初のスモークテストは手動で確認できる程度に小さく保ってください。
よくある質問
キーを設定しているのに、なぜOpenAI互換APIは401を返すのですか?
変更したものとは別の環境変数をプロセスが読んでいるか、キーが別のプロバイダーのものかもしれません。解決された変数名、Authorization: Bearer ヘッダー、コピー時に入った空白、アカウントやIPのポリシーを確認してください。
SDKのbase URLに /chat/completions を含めるべきですか?
通常はいいえです。SDKには /v1 のベースURLを渡し、エンドポイントの追加はSDKに任せてください。完全なエンドポイントを渡すと、パスが重複することがよくあります。
なぜモデルはストリーミングなしでは動くのに、stream: true だと失敗するのですか?
ベースルートは正しくても、バッファリングのミドルウェア、SSEパーサーの不一致、またはストリーミングをサポートしないルート/モデルの組み合わせによって、ストリーミング経路がブロックされている可能性があります。フロントエンドコードをデバッグする前に、curl -N でテストしてください。
有効なモデル名なのに、なぜ「model not found」になるのですか?
あるエンドポイントファミリーでは有効でも別のファミリーでは無効なエイリアスかもしれませんし、ゲートウェイが直接プロバイダーとは異なるエイリアスを公開している可能性もあります。現在のコンソールのエイリアスとエンドポイントファミリーを一緒に確認してください。
本番トラフィックを送る前に何をテストすべきですか?
ストリーミングなしのリクエストを1回、SDKリクエストを1回、ストリームを1回、アプリがツールを使うなら代表的なツール呼び出しを1回、失敗経路を1回、そして請求/読み戻しの記録を1回テストしてください。そのうえで、以前のプロバイダールートのロールバック設定を保持してください。
OpenAI互換APIのトラブルシューティングは、あらゆるプロバイダーのエラーを暗記することではありません。キーからベースURL、ベースURLからエンドポイントファミリー、エンドポイントファミリーからモデルエイリアス、成功したレスポンスから使用量記録までの経路を証明することです。これらのレイヤーが明確になれば、Flatkey経由でトラフィックを切り替えることは、深夜のデバッグ作業ではなく、制御された移行になります。



