Claude web_searchのエラーコード一覧と対処法
Claude APIのweb_searchサーバーツールが返す6種類のエラーコードと、200成功扱いで返る特殊な形式、400との切り分け、コード別の対処方針をまとめます。
Claude APIのweb_searchツールがエラーを起こしても、レスポンスのステータスは200のままです。is_errorフラグを見るクライアントツール用の実装を流用すると、エラーを検知できずに素通りさせてしまいます。ここではweb_searchが返す6種類のエラーコードと、400で落ちるケースとの切り分け、コードごとの対処方針を扱います。
web_searchのエラーはis_errorを使わない
クライアントツール(自前のコードで実行する関数)のエラーは、tool_resultブロックに"is_error": trueを立てて返します。サーバーツール(Anthropicの実行環境内で動くツール)のweb_searchは、別の形式を使います。
エラーの表し方の違い
クライアントツール
アプリがtool_resultを組み立て、失敗したら"is_error": trueと原因の文面を入れます。文面にはClaudeが次に試すことまで書くよう、公式が勧めています。
web_search
Anthropic側がweb_search_tool_resultを返し、失敗時はcontentが単一のエラーオブジェクトに置き換わります。ステータスは200で、is_errorは使いません。
公式が示すエラー時のJSONは次の形です。
{
"type": "web_search_tool_result",
"tool_use_id": "srvtoolu_a93jad",
"content": {
"type": "web_search_tool_result_error",
"error_code": "max_uses_exceeded"
}
}エラーかどうかはcontent.typeがweb_search_tool_result_errorかで判定します。正常時のcontentは検索結果のリストです。検索が成功して0件だった場合はエラーではなく空のリストが返るため、「contentが空か」だけで判定すると、0件ヒットをエラー扱いしてしまいます。
サーバーツールのエラーについて、Handle tool callsページは「Claudeが透過的に処理し、代替の回答や説明を返そうとする」と説明し、is_errorの処理は不要としています。アプリ側でエラーコードを拾う価値は、再試行や上限の調整、ログと監視にあります。
6つのエラーコードの意味と対処
error_codeが取りうる値は次の6種類です。右列は公式の記述ではなく、各コードの意味から導いた対処の一例です。
| error_code | 意味 | 対処の一例 |
|---|---|---|
too_many_requests | 意味レート制限を超過した | 対処の一例指数バックオフで再試行 |
invalid_tool_input | 意味検索クエリのパラメータが不正 | 対処の一例クエリを検証してから再送 |
max_uses_exceeded | 意味max_usesの検索回数の上限に達した | 対処の一例max_usesの設定値を見直す |
query_too_long | 意味クエリが最大長を超えている | 対処の一例クエリを短くして再送 |
request_too_large | 意味検索リクエストが大きすぎる(典型的にはドメインフィルタが長い) | 対処の一例allowed_domains / blocked_domainsの件数を減らす |
unavailable | 意味Anthropic側の内部エラー | 対処の一例再試行 |
max_uses_exceededは、Claudeがmax_usesを超えて検索しようとしたときに出ます。簡単な事実確認なら検索は1〜3回で済み、比較や複数対象の調べものでは10回以上に達することもあると、公式は目安を示しています。上限を絞りすぎるとこのエラーが増えます。
400で落ちるのか、200で返るのか
error_codeが入るのは、リクエストが受理されて検索の実行段階で失敗したときだけです。形式の不正など手前の段階では、通常の400 invalid_request_errorとしてリクエスト全体が拒否されます。error_codeだけを見るハンドラでは、この400を取りこぼします。
エラー応答の判定順序
- 1
HTTPステータスを見る
400ならリクエスト自体の不備です。次のカードの原因を順に疑います。error_codeは含まれません。 - 2
stop_reasonを見る
pause_turnは再開が必要な一時停止、tool_useはクライアントツールの結果待ちです。どちらもエラーではありません。 - 3
web_search_tool_resultのcontent.typeを見る
web_search_tool_result_errorのときだけerror_codeで分岐します。リストなら正常な検索結果です。
400になる代表的な原因は、公式ドキュメントに次のとおり書かれています。
400で落ちる原因
組織で無効化されている
管理者がClaude Consoleで
web_searchを無効化していると、ツールを含むリクエストは「web search is not enabled」という趣旨の400になります。error_codeにはなりません。ドメインフィルタの指定ミス
allowed_domainsとblocked_domainsの同時指定、スキーム付きのURL、*.example.comのようなドメイン部分のワイルドカードは、いずれも400です。ワイルドカードを使えるのはパス側(example.com/*)だけです。組織の制限との衝突
リクエスト側の
allowed_domainsは、Consoleで設定した組織側の許可リストの部分集合でなければなりません。組織がブロックしているドメインを含めると、衝突した項目名つきの400で拒否されます。user_locationの国コード
countryにはISO 3166-1 alpha-2の2文字コードを渡します。サポート外のコードは400です。allowed_callersの未指定
プログラム的ツール呼び出しに対応しないモデルでは、
allowed_callers: ["direct"]を付けずに呼ぶと400になり、メッセージで設定を促されます。encrypted_contentの欠落・改変
複数ターンの会話で、前の検索結果の
encrypted_contentを欠かしたり書き換えたりすると、検証エラーの400です。アシスタントのブロックは受け取ったまま送り返します。
request_too_largeと400は、どちらもドメイン一覧が原因になりえます。書式が不正なら400です。request_too_largeは、公式の説明どおり典型的にはドメインフィルタの一覧が長いときに出ます。
ドキュメントによってコード名の一覧が食い違う
web_searchのエラーコードは、公式ドキュメントの2か所に書かれていて、内容が一致しません。
| ページ | 挙げているコード | 無効な入力のコード名 |
|---|---|---|
| web_searchツール専用ページ(Errors節) | 挙げているコード6種類 | 無効な入力のコード名invalid_tool_input |
| Handle tool callsページ(Server tool errors) | 挙げているコード5種類(request_too_largeなし) | 無効な入力のコード名invalid_input |
JSON構造の例、ストリーミング、課金ルールまで持つのは専用ページです。実装は専用ページの6種類を前提にし、一覧にないコード文字列が来たときはログを残して処理を止める分岐を置く、という選択肢があります。一般ページの5種類だけで分岐を書くと、request_too_largeがどの分岐にも当たりません。
コードでの実装例
HTTPレスポンスのJSONをそのまま扱う例です(SDKの型付きオブジェクトではなく、response.json()で得た辞書を想定しています)。400のエラー本文にはcontentキーがないので、ステータスを先に見て分岐します。そのうえでcontentがリストかオブジェクトかを分けます。
def handle_response(response):
if response.status_code != 200:
handle_http_error(response) # 400など。content も error_code も無い
return
data = response.json()
for block in data["content"]:
if block["type"] != "web_search_tool_result":
continue
result = block["content"]
if isinstance(result, list):
handle_results(result) # 0件なら空リスト。エラーではない
continue
code = result["error_code"]
if code in ("too_many_requests", "unavailable"):
retry_with_backoff()
elif code == "max_uses_exceeded":
notify_budget_exhausted()
elif code in ("invalid_tool_input", "query_too_long"):
log_bad_query(result)
elif code == "request_too_large":
shrink_domain_filters()
else:
log_unknown_error_code(code) # 一覧にないコードの受け皿エラーコードの比較は文字列の完全一致で足ります。複数フィールドをまとめて比較・キャッシュする実装では、JSON文字列同士の比較を避けてフィールド単位で比べます。理由はJSON文字列比較で起きるエスケープ差分の罠にあります。
pause_turnとtool_useはエラーではない
長いターンでは、サーバー側のループを区切ってstop_reason: "pause_turn"が返ることがあります。エラーではなく、一時停止したアシスタントメッセージを変更せずに次のリクエストへ含めて送り直せば、続きが進みます。再開のときの注意は3点です。
- 送り直すリクエストには、同じ
toolsを含める。未実行のserver_tool_useで止まっている場合、そのツールが無いと検証エラーになる - 再開後に再び
pause_turnになることがあるので、stop_reasonを毎回確認し、再開回数に上限を設ける - Batches APIでもループ回数の上限に達すると同じ
pause_turnで終わり、返ってきた内容を付けた追加リクエストで続ける
stop_reasonとHTTPエラーを混同しない設計はstop_reasonとエラーの違いで扱っています。
同じ並列呼び出しの中でweb_searchとクライアントツールが両方呼ばれた場合は、stop_reasonがtool_useになり、検索はまだ実行されません。クライアントツールの結果だけをtool_resultで返すと、次のリクエストで検索が走ります。このtool_useもweb_searchのエラーではなく、error_codeの有無で分岐していれば取り違えません。
BatchesとストリーミングとAWS・Google Cloud
Messages Batches APIのweb_searchは、料金がMessages APIと同じです。共有キャパシティの保護のため、Batches APIは組織単位でweb_searchのリクエストを絞り、検索の多い大きなバッチは完了まで時間がかかることがあります。組織の上限はClaude Consoleの「Rate limits」ページで見られ、引き上げはそのページから営業窓口に依頼します。
ストリーミングでは、検索結果がweb_search_tool_resultのcontent blockとしてcontent_block_startイベントで届き、検索の実行中は一時停止が入ります。
使える環境にも差があります。web_searchはClaude APIのほか、AWS上のClaude Platform、Microsoft Foundryで使えます。ただしAzure上でホストされたFoundryのデプロイは、動的フィルタなしの基本版(web_search_20250305)だけです。Google Cloudも基本版のみで、Amazon Bedrockでは使えません。Claude Mythos Previewは、Claude Platform on AWSでも使えません。
課金はエラー発生時にどうなるか
web_searchは1,000検索あたり10ドルの従量課金で、結果の件数に関わらず1回の検索を1回分と数えます。検索中にエラーが起きた場合、その検索は課金されません。再試行が成功した分は、通常の検索1回として数えられます。入力トークンへの積み上がりを含む費用の見方はClaude APIのweb_search料金にあります。
Claude Codeやclaude.aiのWeb検索とは別物
ここで扱ったのは、Messages APIからweb_searchツールを直接呼んだときのerror_codeの形式です。Claude Codeやclaude.aiのWeb検索は別の使い方になります。エンドユーザー向けの挙動の違いはClaude Web検索の使い方にあります。
ツール呼び出し全般の設計はAnthropic Advanced Tool Useを、会話履歴の不整合など別系統のtool_use関連エラーはthinking block mismatchエラーの原因とrewindでの直し方が参考になります。
よくある質問
エラーコードの分岐はどうテストするか
too_many_requestsやunavailableは、通常の利用では意図的に出せません。error_codeを直接入れたモックのレスポンスJSONを用意して、分岐ごとにユニットテストを書く方法が現実的です。max_uses_exceededはmax_usesを小さく設定すれば到達できる条件なので、実機で試す場合の候補になります。
まとめ
web_searchのエラーは、HTTPステータスやis_errorではなくcontent.typeで見分けます。400は設定の不備、200のweb_search_tool_result_errorは実行段階の失敗、と先に分けてからerror_codeで分岐し、一覧にないコードにも受け皿を置いておくと、2か所で食い違う公式の一覧にも耐えられます。