エラー処理
失敗したリクエストは、HTTP ステータスコードと、エラータイプとメッセージを含む JSON ボディを返します。このページでは、すべてのステータスを一覧にし、各 API 形式のエラーボディを示し、再送信する価値のあるエラーを説明します。
SDK は、ステータスコードとボディのフィールドを持つエラーオブジェクトを発生させます。このリクエストは、存在しないモデルを指定しています。
import openai
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://api.shannon-ai.com/v1",
)
try:
client.chat.completions.create(
model="no-such-model",
messages=[{"role": "user", "content": "Hello"}],
)
except openai.APIStatusError as error:
print(error.status_code) # 400
print(error.type) # invalid_request_error
print(error.body["message"]) # unknown model: no-such-model
print(error.response.headers.get("x-request-id")) # the id of this request import OpenAI from "openai";
const client = new OpenAI({
apiKey: "YOUR_API_KEY",
baseURL: "https://api.shannon-ai.com/v1",
});
try {
await client.chat.completions.create({
model: "no-such-model",
messages: [{ role: "user", content: "Hello" }],
});
} catch (error) {
if (!(error instanceof OpenAI.APIError)) throw error;
console.log(error.status); // 400
console.log(error.type); // invalid_request_error
console.log(error.error.message); // unknown model: no-such-model
} curl -i https://api.shannon-ai.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "no-such-model",
"messages": [{"role": "user", "content": "Hello"}]
}' ステータス 400 と、次のボディが返されます。
{
"error": {
"type": "invalid_request_error",
"message": "unknown model: no-such-model"
}
} エラーボディ
ボディは二種類あります。/v1/messages は Anthropic 形式で応答し、それ以外のエンドポイントはすべて OpenAI 形式で応答します。どちらも詳細は error.type と error.message にあるため、ひとつの読み取り処理で全エンドポイントに対応できます。
{
"error": {
"type": "authentication_error",
"message": "Invalid API key",
"code": "invalid_api_key",
"param": null
}
} {
"type": "error",
"error": {
"type": "authentication_error",
"message": "Invalid API key"
}
} | フィールド | 型 | 説明 |
|---|---|---|
error.type | string | エラーの種類。下記の「エラータイプ」を参照してください。 |
error.message | string | 人間向けの一文。以下の表のテキストは、<id>、<n>、… で示す可変部分を除き、固定です。 |
error.code | string | null | OpenAI 形式の一部のエラーに含まれます:401 では invalid_api_key、413 では request_too_large、会話が長すぎる場合は context_length_exceeded、それ以外は null または存在しません。まずステータスと error.type で判断し、code は補足として扱ってください。 |
error.param | null | code と同じエラーに含まれます。常に null。 |
type | string | Anthropic 形式のみ。常に error。 |
エラータイプ
| タイプ | ステータス | 説明 |
|---|---|---|
invalid_request_error | 400, 413, 415, 422 | リクエスト自体が誤っています。フィールド、ボディ、モデル ID、またはモデルが受け付けない入力です。再送信する前にリクエストを変更してください。 |
authentication_error | 401 | API キーがないか、不明、または無効化されています。 |
not_found_error | 404 | パスが存在しません。 |
rate_limit_error | 429 | 残高がリクエストをまかなえないか、フラッド保護が止めたか、モデルがビジー状態です。どれかはメッセージで分かります。 |
api_error | 500, 502, 503, 504 | リクエストは正しく、失敗の原因はこちら側にあります。もう一度送信してください。 |
server_error | 500 | リクエストは正しく、失敗の原因はこちら側にあります。もう一度送信してください。 |
ステータスコード
| ステータス | タイプ | メッセージ | 発生条件 |
|---|---|---|---|
400 | invalid_request_error | Failed to parse the request body as JSON: … | ボディが有効な JSON ではありません。 |
400 | invalid_request_error | unknown model: <id> | model が公開されている ID ではありません。/v1/responses では model がない場合も同様です。 |
400 | invalid_request_error | No user message provided | Shannon ティア:リクエストにユーザーのテキストがありません。 |
400 | invalid_request_error | <id> does not accept image input | 画像入力に対応していないホスト型オープンウェイトモデルに画像が送信されました。 |
400 | invalid_request_error | audio and video input are not supported by any hosted model | 音声または動画のパートが、ホスト型オープンウェイトモデルに送信されました。 |
400 | invalid_request_error | <id> does not accept response_format | 構造化出力に対応していないホスト型オープンウェイトモデルに、構造化出力が要求されました。 |
400 | invalid_request_error | <id> does not accept response_format json_schema; use json_object | json_object にしか対応していないホスト型オープンウェイトモデルに、JSON スキーマが送信されました。 |
400 | invalid_request_error | unknown reasoning effort '<value>'; expected off, low, medium or high | 推論 effort が、一覧にある値のいずれでもありません。ホスト型オープンウェイトモデル。 |
400 | invalid_request_error | count_tokens is available for the hosted open models; unknown model: <id> | ホスト型オープンウェイトモデル以外のモデルに対して、トークンカウントが要求されました。 |
401 | authentication_error | Missing authentication | API キーが送信されていません。 |
401 | authentication_error | Invalid API key | キーが不明、新しいキーに置き換えられた、または無効化されています。 |
404 | not_found_error | Not Found | パスが存在しません。たとえば /v1/embeddings です。 |
405 | api_error | Method Not Allowed | パスは存在しますが、この HTTP メソッドでは存在しません。 |
413 | invalid_request_error | Failed to buffer the request body: … | リクエストボディが 32 MiB を超えています。 |
415 | invalid_request_error | Expected request with `Content-Type: application/json` | Content-Type ヘッダーがないか、application/json ではありません。 |
422 | invalid_request_error | Failed to deserialize the JSON body into the target type: … | messages など必須のフィールドがないか、フィールドの JSON 型が正しくありません。 |
429 | rate_limit_error | Quota exceeded. Upgrade your plan at shannon-ai.com/plan | リクエストの出力上限が、残高の残りより大きくなっています。 |
429 | rate_limit_error | Too many requests. Retry in <n>s. | フラッド保護:アカウントで一分間に 120 を超えるリクエストがありました。<n> は、その一分が終わるまでの秒数です。 |
429 | rate_limit_error | Shannon Coder call quota reached. Upgrade your plan at shannon-ai.com/plan | /v1/chat/completions と /v1/messages の shannon-coder-1:現在の 4 時間枠で、ご利用プランの Shannon Coder の呼び出し回数を使い切りました。 |
429 | rate_limit_error | Shannon routes are temporarily busy. Please retry. | 現在、モデルがビジー状態です。 |
500 | server_error | The model backend failed to answer. Please retry. | モデルが応答を生成しませんでした。 |
500 | server_error | An internal error occurred. Please retry. | リクエストの準備中に内部障害が発生しました。 |
502 | api_error | The model backend failed to answer. Please retry. | モデルが応答を生成しませんでした。Shannon 3 ファミリーとホスト型オープンウェイトモデル。 |
503 | api_error | Could not verify your quota right now. Please retry. | 現在、残高を読み取れませんでした。 |
503 | api_error | token counting is temporarily unavailable for this model | 現在、このモデルではトークンカウントを利用できません。 |
504 | api_error | upstream timed out | ホスト型オープンウェイトモデルが、ストリームでないリクエストの制限時間を超えました。 |
チェックは、API キー、リクエストボディ、モデル ID、フラッド保護、残高の順に実行されます。そのため、キーもボディも誤っているリクエストには 401 が返されます。4xx ステータスで拒否されたリクエストは課金されません。
残高とフラッド保護
すべてのリクエストは平等に処理されます。レートのティアも、API 専用の枠もありません。それでも 429 で応答するものがふたつあり、どちらもタイプは rate_limit_error です。メッセージで見分けられます。
残高
残高は、本日のプラン枠(00:00 UTC にリセット)と、その後に使われる購入済みクレジットです。チャットと API は同じ残高から消費されます。
各リクエストは、まず出力上限分を確保します。max_tokens、/v1/responses では max_output_tokens、どちらも送信しない場合は 4,096 です。応答が完了すると、確保した量はリクエストが実際に使用した量に置き換えられます。確保する量が残りの残高に収まらない場合、モデルが開始される前にリクエストは Quota exceeded を返します。
同時に実行されるリクエストは、それぞれ自分の分を確保します。そのため、max_tokens の大きい並列リクエストが多数あると、各応答が短くても、一時的に残高を使い切ることがあります。max_tokens を小さくすると、確保される量が減ります。
フラッド保護
フラッド保護は、アカウントあたり一分間に 120 リクエストまで許可します。対象はキーではなくアカウントで、/v1/chat/completions、/v1/responses、/v1/messages の合計で数えます。この一分間は、最初のリクエストから始まります。
その一分間の 121 番目のリクエストには Too many requests. Retry in <n>s. が返され、課金されません。拒否されたリクエストも数えられるため、待たずに再送信するクライアントは、一分が終わるまで拒否され続けます。メッセージにある <n> 秒待ってください。
並列に送信されたリクエストが、並列であることを理由に拒否されることはありません。順番待ちになり、順に応答されます。
GET /v1/models とトークンカウント用エンドポイントは数えられません。
上限と残高の詳細、およびご自身の残高と使用量の確認場所: 上限と残高 キーと使用量
再試行すべきもの
同じリクエストが成功しうる場合にのみ、再送信してください。OpenAI と Anthropic の SDK は、429 と 5xx の応答を自動的に二回再試行します。変更するには max_retries(JavaScript では maxRetries)を設定します。
| エラー | 再送信してよいか | 方法 |
|---|---|---|
400, 404, 405, 413, 415, 422 | いいえ。先にリクエストを修正してください。 | メッセージに、誤っているフィールド、モデル、入力が示されます。 |
401 | いいえ。有効なキーを使ってください。 | キーと使用量のページで、キーを作成または置き換えてください。 |
429 Too many requests | はい。待機後に。 | メッセージにある秒数だけ待ってから、同じリクエストを送信します。 |
429 Quota exceeded | そのままでは不可。 | max_tokens を小さくするか、00:00 UTC の日次リセットを待つか、クレジットを追加してください。 |
429 Shannon Coder call quota reached | はい。次の枠で。 | 枠は UTC の 00:00 から 4 時間ごとに始まります。別のモデルならすぐに応答します。 |
429 … temporarily busy | はい。 | 数秒待ち、再試行のたびに待ち時間を延ばします。 |
500, 502, 503 | はい。 | 1 秒待ち、次に 2 秒、4 秒、8 秒と待ちます。数回試したら中止し、リクエスト ID を報告してください。 |
504 | はい。 | stream を true にして送信してください。時間制限が適用されるのは、ストリームでない応答です。 |
この表に従った再試行ループ:
import re
import time
import openai
from openai import OpenAI
# max_retries=0: this loop does the retrying, the SDK does not add its own.
client = OpenAI(api_key="YOUR_API_KEY", base_url="https://api.shannon-ai.com/v1", max_retries=0)
def create_with_retry(attempts=5, **request):
for attempt in range(attempts):
try:
return client.chat.completions.create(**request)
except openai.RateLimitError as error:
text = str(error)
flood = re.search(r"Retry in (\d+)s", text)
if flood:
time.sleep(int(flood.group(1))) # flood protection: wait out the minute
elif "temporarily busy" in text:
time.sleep(2 ** attempt)
else:
raise # balance: a wait of seconds does not help
except (openai.InternalServerError, openai.APIConnectionError):
time.sleep(2 ** attempt) # 1, 2, 4, 8 seconds
raise RuntimeError("the request failed after all attempts")
response = create_with_retry(
model="shannon-3",
messages=[{"role": "user", "content": "Hello"}],
)
print(response.choices[0].message.content) import OpenAI from "openai";
// maxRetries: 0 — this loop does the retrying, the SDK does not add its own.
const client = new OpenAI({ apiKey: "YOUR_API_KEY", baseURL: "https://api.shannon-ai.com/v1", maxRetries: 0 });
const sleep = (seconds) => new Promise((resolve) => setTimeout(resolve, seconds * 1000));
async function createWithRetry(request, attempts = 5) {
for (let attempt = 0; attempt < attempts; attempt++) {
try {
return await client.chat.completions.create(request);
} catch (error) {
const text = String(error.message);
const flood = text.match(/Retry in (\d+)s/);
if (error.status === 429 && flood) {
await sleep(Number(flood[1])); // flood protection: wait out the minute
} else if (error.status === 429 && text.includes("temporarily busy")) {
await sleep(2 ** attempt);
} else if (error.status >= 500 || error instanceof OpenAI.APIConnectionError) {
await sleep(2 ** attempt); // 1, 2, 4, 8 seconds
} else {
throw error; // wrong request, wrong key or balance
}
}
}
throw new Error("the request failed after all attempts");
}
const response = await createWithRetry({
model: "shannon-3",
messages: [{ role: "user", content: "Hello" }],
});
console.log(response.choices[0].message.content); ストリーム内のエラー
ストリームは最初のバイトからステータス 200 です。その後の失敗は、ストリーム内のイベントとして届きます:/v1/chat/completions では error メンバーを持つチャンク、/v1/messages では error イベント、/v1/responses では response.failed または error イベントです。ストリームの終了イベントはその後も続きます。このような応答は失敗として扱い、5xx ステータスの場合と同じようにリクエストを再送信してください。
モデルのコンテキストウィンドウより長い会話は、この形で報告され、タイプは invalid_request_error、コードは context_length_exceeded です。再送信する前に会話を短くしてください。
正確なフレームについては、ストリーミングの説明を参照してください。 ストリーミング
リクエスト ID
エラーを含むすべての応答に x-request-id ヘッダーが付きます。独自の x-request-id ヘッダーで送信した値、または何も送信しなかった場合は十六進数 12 文字の値です。ログに記録し、リクエストについて問い合わせるときに添えてください。