Claude APIのエラー形式とSDK例外クラスの言語別対応表
Claude APIが返すエラーのJSON形式と、Python・TypeScript・Go・Ruby・Java・PHP・C#の7言語でSDKが投げる例外クラスの対応表をまとめます。
Claude APIのエラーはtypeとmessageの2フィールドで統一されている
Claude APIはエラーを常にJSONで返します。トップレベルのerrorオブジェクトがtypeとmessageを必ず持ち、レスポンス全体には追跡用のrequest_idも付きます(request-idをサポート問い合わせで使う方法は、エラー調査の初動で必ず控えておきたい値です)。フォーマットは全エンドポイント共通です。
{
"type": "error",
"error": {
"type": "not_found_error",
"message": "The requested resource could not be found."
},
"request_id": "req_011CSHoEeqs5C35K2UUqR7Fy"
}公式SDKはこの生JSONをそのまま返さず、言語ごとに用意した型付き例外に変換して投げます。クラス名も名前空間も言語によってバラバラで、Goだけは他の6言語と設計そのものが違います。この記事は、Python・TypeScript・Ruby・Java・PHP・C#・Goの7言語について、ステータスコードと例外クラスの対応を1枚の表にまとめた早見表です。個別のリトライ設計やストリーミング中のエラー回復はClaude APIのエラーハンドリング設計に譲り、ここでは複数言語のSDKを併用する実装者が例外クラス名を引くための一覧に絞ります。
ステータスコード別のエラー型と例外クラスの対応表
まずHTTPステータスコードとerror.typeの対応です。この値はSDKを使わず生JSONを扱うときにも参照します。
| ステータス | error.type | 意味 |
|---|---|---|
| 400 | error.typeinvalid_request_error | 意味リクエストの形式・内容の不備 |
| 401 | error.typeauthentication_error | 意味APIキーの不備・失効 |
| 402 | error.typebilling_error | 意味支払い情報の問題 |
| 403 | error.typepermission_error | 意味権限不足 |
| 404 | error.typenot_found_error | 意味リソースが見つからない |
| 409 | error.typeconflict_error | 意味リソースの状態衝突 |
| 413 | error.typerequest_too_large | 意味リクエストサイズ超過 |
| 429 | error.typerate_limit_error | 意味レート制限・利用上限到達 |
| 500 | error.typeapi_error | 意味Anthropic側の内部エラー |
| 504 | error.typetimeout_error | 意味処理中のタイムアウト |
| 529 | error.typeoverloaded_error | 意味APIの一時的な過負荷 |
413(request_too_large)はエンドポイントごとにリクエストサイズの上限が違います。
| エンドポイント | 上限 |
|---|---|
| Messages API | 上限32MB |
| Token Counting API | 上限32MB |
| Batch API | 上限256MB |
| Files API | 上限500MB |
413は上の例外クラス一覧に個別のクラスを持ちません。Python・TypeScript・Ruby・PHPはいずれも409や422と違って413専用のクラス名を定義しておらず、汎用のAPIStatusError(PHPはAPIStatusException)にフォールバックします。直接APIを叩く構成では、Cloudflareがリクエストサーバーに到達する前にこのエラーを返す点も、Anthropic側のログに残らない原因になるので覚えておく価値があります。
次に、各言語のSDKがこれらのステータスに対して投げる例外クラスです。Python・TypeScript・Ruby・PHPは同じ命名パターン(BadRequestError系)を採用しており、JavaとC#はException接尾辞、Goだけ単一の構造体でステータスを分岐します。
| ステータス | Python | TypeScript | Ruby | Java | PHP | C# |
|---|---|---|---|---|---|---|
| 400 | PythonBadRequestError | TypeScriptBadRequestError | RubyBadRequestError | JavaBadRequestException | PHPBadRequestException | C#AnthropicBadRequestException |
| 401 | PythonAuthenticationError | TypeScriptAuthenticationError | RubyAuthenticationError | JavaUnauthorizedException | PHPAuthenticationException | C#AnthropicUnauthorizedException |
| 403 | PythonPermissionDeniedError | TypeScriptPermissionDeniedError | RubyPermissionDeniedError | JavaPermissionDeniedException | PHPPermissionDeniedException | C#AnthropicForbiddenException |
| 404 | PythonNotFoundError | TypeScriptNotFoundError | RubyNotFoundError | JavaNotFoundException | PHPNotFoundException | C#AnthropicNotFoundException |
| 409 | PythonConflictError | TypeScriptConflictError | RubyConflictError | Java— | PHPConflictException | C#— |
| 422 | PythonUnprocessableEntityError | TypeScriptUnprocessableEntityError | RubyUnprocessableEntityError | JavaUnprocessableEntityException | PHPUnprocessableEntityException | C#AnthropicUnprocessableEntityException |
| 429 | PythonRateLimitError | TypeScriptRateLimitError | RubyRateLimitError | JavaRateLimitException | PHPRateLimitException | C#AnthropicRateLimitException |
| 5xx | PythonInternalServerError | TypeScriptInternalServerError | RubyInternalServerError | JavaInternalServerException | PHPInternalServerException | C#Anthropic5xxException(base: AnthropicApiException) |
Python・TypeScript・Ruby・PHPの基底クラスはそれぞれAPIError / APIError / Anthropic::Errors::APIError / Anthropic\Core\Exceptions\APIExceptionです。Javaの基底はAnthropicServiceException(全例外の頂点はAnthropicException)、C#はAnthropicApiException(頂点はAnthropicException)。409(競合)はJavaとC#の表に個別クラスがなく、Javaはothers扱いのUnexpectedStatusCodeException、C#はAnthropicUnexpectedStatusCodeExceptionに落ちます。
基底クラスと4xx/5xxのまとめ方は言語ごとに違う
個別の例外クラスとは別に、言語ごとに用意された基底クラスの構造も異なります。Python・TypeScriptはAPIErrorを頂点に、ネットワーク到達不能をAPIConnectionError、非2xxレスポンスをAPIStatusErrorのサブクラスに分けます。RubyもPythonと同じ2分岐構造で、基底はAnthropic::Errors::APIErrorです。PHPはAnthropic\Core\Exceptions\APIExceptionが頂点で、APIConnectionException・APIStatusException・RateLimitExceptionのサブクラスに分岐します。
Javaは構造が異なり、頂点はAnthropicException、HTTPエラーの基底はAnthropicServiceExceptionです。加えてI/Oエラー専用のAnthropicIoException、リトライ可能な失敗を示すAnthropicRetryableException、レスポンスのパース失敗を示すAnthropicInvalidDataExceptionが並列に存在し、Pythonのような単純な2分岐にはなっていません。C#もAnthropicExceptionが頂点ですが、APIエラーの基底はAnthropicApiExceptionで、すべての4xx系例外はAnthropic4xxExceptionを継承する中間クラスを挟みます。ストリーミング中のエラーも専用のAnthropicSseExceptionとして独立しており、通常のステータスコード分岐とは別枠です。
例外オブジェクトから読み取れるプロパティ
catchした例外から何を読み取れるかも言語で書き方が変わります。ステータスコードやレスポンス本体へのアクセス方法を揃えておくと、ログ出力用のラッパー関数を各言語で書くときに迷いません。
| 言語 | ステータスコード | レスポンス本体 |
|---|---|---|
| Python | ステータスコードe.status_code | レスポンス本体e.response |
| TypeScript | ステータスコードerr.status | レスポンス本体err.headers |
| Ruby | ステータスコードe.status | レスポンス本体— |
| Java | ステータスコードe.statusCode() | レスポンス本体e.headers() |
| Go | ステータスコードapierr.StatusCode | レスポンス本体apierr.Response / apierr.Request |
| C# | ステータスコードraw responseアクセサ経由 | レスポンス本体raw responseアクセサ経由 |
| PHP | ステータスコードe->getMessage() | レスポンス本体e->getPrevious()(接続エラー時) |
C#のみ、例外自体からは直接ステータスやヘッダーを取れず、WithRawResponseのraw responseアクセサ経由で読む設計です。これは後述するリクエストIDの取得方法と同じ非対称性で、C#・Go・Java・PHPはraw response経由、Python・TypeScriptはオブジェクトのプロパティに直接生えている、という2グループに分かれます。
タイムアウトと接続エラーは専用クラスに分かれる
ここまでの対応表には載らない2種類のエラーも、複数言語のSDKを扱うなら押さえておく必要があります。ネットワークに到達できない接続エラーと、リクエストがタイムアウトしたエラーです。
| 言語 | 接続エラー | タイムアウト |
|---|---|---|
| Python | 接続エラーAPIConnectionError | タイムアウトAPITimeoutError |
| TypeScript | 接続エラーAPIConnectionError | タイムアウトAPIConnectionTimeoutError |
| Ruby | 接続エラーAPIConnectionError | タイムアウトAPITimeoutError |
| PHP | 接続エラーAPIConnectionException | タイムアウトAPITimeoutException |
| Java | 接続エラー専用クラスの記載なし(I/O例外として扱われます) | タイムアウト専用クラスの記載なし(I/O例外として扱われます) |
| C# | 接続エラー専用クラスの記載なし(I/O例外として扱われます) | タイムアウト専用クラスの記載なし(I/O例外として扱われます) |
| Go | 接続エラー*url.Error(*net.OpErrorを包む) | タイムアウト明示的な専用型なし |
Python・TypeScript・Ruby・PHPはHTTPステータスを持たないこの2種類を独立クラスとして分けているのに対し、公式ドキュメント上はJavaとC#について接続エラー・タイムアウトそれぞれの専用クラスが明記されておらず、I/O例外(JavaはAnthropicIoException、C#はAnthropicIOException。JavaにはAnthropicRetryableExceptionという別系統のクラスも存在します)として扱われる形です。Java・C#は接続エラーとタイムアウトを分ける専用クラスを公式ドキュメントに記載していないため、PythonのAPIConnectionError/APITimeoutErrorに相当するcatchの分割は、そのままでは持ち込めません。非ストリーミングのMessagesリクエストは約10分でタイムアウトする挙動が全SDK共通の既定値で、ストリーミングに切り替えるか、クライアント・リクエスト単位のタイムアウト設定で回避します。
Goだけ型付き例外を使わずStatusCodeで分岐する
Goのanthropicパッケージには、ほかの6言語のようなNotFoundErrorやRateLimitExceptionは存在しません。返るのは単一の*anthropic.Error型で、StatusCodeフィールドと元の*http.Request・*http.Response、エラー本文のJSONを保持します。
var apierr *anthropic.Error
if errors.As(err, &apierr) {
if apierr.StatusCode == 404 {
// not_found_errorとして処理
}
}
panic(err.Error()) // POST "/v1/messages": 400 Bad Request (Request-ID: req_xxx) { ... }これはGoの言語設計(例外機構がなくエラー値を返す)に合わせた結果で、他言語より情報が少ないわけではありません。StatusCodeをキーに、上の対応表のerror.type列と突き合わせれば同じ分岐ができます。HTTPトランスポート自体が失敗した場合は*anthropic.Errorではなく*url.Errorが*net.OpErrorを包んで返ります。
文字列マッチでなく型で分岐すると何が起きるか
error.messageは人間向けの説明文で、Anthropicのバージョニングポリシー上、typeの値は今後増える可能性があります。メッセージ文字列やtype文字列の完全一致でハンドリングを書くと、文言変更や新しいtype追加でロジックが壊れます。公式が推奨するのは、SDKが提供する型付き例外クラスでcatchし、より具体的なクラスから先に処理する順序です。
try:
message = client.messages.create(...)
except anthropic.NotFoundError:
# 404を個別処理
except anthropic.RateLimitError as e:
# 429を個別処理
except anthropic.APIStatusError as e:
# その他の4xx/5xxをまとめて処理Java・C#でも同じ順序原則が働きますが、基底クラスの構造がPython系と違うぶん、catchの並べ方も変わります。
try {
Message message = client.messages().create(params);
} catch (RateLimitException e) {
// 429を個別処理
} catch (UnauthorizedException e) {
// 401を個別処理
} catch (AnthropicServiceException e) {
// その他のHTTPエラーをまとめて処理(statusCode()で分岐)
}Python・TypeScript・Ruby・PHPは基底クラスが共通なので、この順序(具体的 → 抽象的)を守るだけで新しいステータスコードにも安全に対応できます。複数言語でマイクロサービスを組んでいるチームがハマりやすいのは、Pythonでの実装をそのままGoに移植し、Goにも同名の例外クラスがあるはずだと探してしまうケースです。GoはStatusCode分岐、それ以外は型分岐という2系統があることを前提に設計します。
リクエストIDでサポートに問い合わせるときの取得方法
各エラーレスポンスにはrequest-idヘッダーが付き、これはエラーオブジェクトのrequest_idフィールドと同じ値です。Anthropicサポートに問い合わせるときはこのIDを添えると調査が早まります。PythonとTypeScriptはレスポンスオブジェクトの_request_idプロパティで直接取得できます。C#・Go・Java・PHPはraw responseアクセサ経由、Rubyはmiddleware経由でヘッダーを読みます。Claude Platform on AWS経由の場合は、AWSリクエストID(x-amzn-requestid)とAnthropicリクエストID(request-id)の2つが返るため、CloudTrail照合にはAWS側、Anthropicサポートへの問い合わせにはAnthropic側のIDを使い分けます。
catchした例外がリトライ済みか修正が必要かの見分け方
例外をcatchしたあと、呼び出し側で追加のリトライが必要か、それとも修正が必要かは、どのクラスかで見分けがつきます。Python・Ruby・PHPは共通して、接続エラー・408・409・429・5xx系は既定で2回まで自動リトライ済みです。つまりRateLimitErrorやConflictErrorをcatchできた時点で、SDKはすでに2回試行を終えています。ここでさらにアプリ側が即座にリトライすると、実質的に過剰なリトライになりレート制限を悪化させかねません。一方BadRequestError(400)やNotFoundError(404)、AuthenticationError(401)はそもそもリトライ対象に含まれません。これらはリクエスト自体を直さない限り再送しても同じ結果になるため、catchした時点でリトライではなく修正が必要というシグナルです。max_retries(Python)・max_retries(Ruby)・maxRetries(PHP)などのオプションで既定のリトライ回数自体を変更することもできます。
この対応表をどう実装に落とすか
複数言語のSDKを横断して使うプロダクトでは、この対応表をそのままエラーハンドリングの設計ドキュメントに転記できます。リトライ設計(どのステータスを何回リトライするか)やレート制限エラーの詳しい対処は別記事の領分です。Agent SDKのエラー集にあるCLINotFoundErrorのような周辺ツール由来の例外は、ここで扱ったMessages APIの例外階層とは別の階層にある点も区別しておくと、原因の切り分けが速くなります。
まとめ
Claude APIのエラーはJSONのtype/messageで統一されていますが、SDKが投げる例外クラス名は言語ごとに異なります。Python・TypeScript・Ruby・PHPはXxxError/XxxExceptionの同型命名、JavaとC#はException接尾辞、Goだけは*anthropic.ErrorとStatusCode分岐という別設計です。複数言語のSDKを併用する実装では、この対応表を手元に置いて型で分岐する実装に統一するのが安全です。