Browser use toolのエラーハンドリング — executor側のis_error規約
Browser use toolでexecutorが失敗をどう返すか、navigateのスキーム拒否やバッチアクション停止の実例から読み解きます。
Browser use toolのエラーはexecutorが形にする
Browser use toolは、Claudeがブラウザを操作するためのbrowser_toolset_20260801というクライアントツールセットです。navigateやleft_clickなど27個のメンバーツールを既定で宣言でき、javascript_execのような残り4つはconfigsで有効化した場合だけ追加されます(最大31個)。実行そのものは常にアプリケーション側のexecutorが担い、Anthropicのサーバーはtool_useブロックを返すだけでブラウザは動かしません。
この構造では、呼び出しが失敗したときにClaudeへ何を返すかがexecutor側の設計事項になります。公式ドキュメントが定める基本形は明快です。失敗した呼び出しは、is_error: true・何が起きたかを書いたtext content・呼び出しと同じtoolset_nameのechoを持つ、通常のエラー結果として返します。このときbrowser_stateブロックは付けません。難しいのは文言の書き方と、navigateのスキーム拒否のような個別ケースの扱いです。
navigateハンドラーで拒否すべきスキーム
セキュリティ上の推奨事項の中でも、navigateハンドラーの実装は具体的な規約を伴います。公式ドキュメントは次の4点を挙げています。
- 履歴操作のキーワード
"back"・"forward"・"reload"を受け付ける - スキームの無いURLは
https://として扱う - URLをパースしたうえで、
http・https以外のスキーム(javascript:・file:・data:・chrome:など)をエラー結果で拒否する - スキームの判定は文字列の前方一致ではなく、URLパーサーで行う
3番目と4番目は対になっています。文字列マッチだけで判定すると、細工されたURLがスキーム拒否をすり抜ける余地が残ります。APIはナビゲーションの中身を検証しないため、拒否できるのはexecutor側だけです。実際に拒否したときのエラー結果は次の形になります。
{
"type": "tool_result",
"tool_use_id": "toolu_01LeUTyqkhRxBFq1QTG3pkwN",
"toolset_name": "browser",
"is_error": true,
"content": "Error: Navigation refused. Only http and https URLs are allowed."
}文言はClaudeが次に何をするかを左右する
エラーのtext contentは、単なる通知ではなくClaudeが読んで行動を調整する入力です。公式ドキュメントはError: navigation failedのような素っ気ない文言と、Error: Navigation to https://example.com/status timed out after 30 seconds. The page may be unavailable.のような具体的な文言を対比し、後者だけがClaudeにとって行動可能な情報になるとしています。何が失敗したURLか、何秒待ったか、ページ側に原因がありそうかまで書き込むと、Claudeは再試行すべきか別の手段に切り替えるべきかを自分で判断できます。何が起きたかに加えて、次にどう解釈すべきかまで書くのが実務上のポイントです。
4つの典型パターンと返すべき文言
公式ドキュメントは、スキーム拒否以外にも3つの典型的な失敗パターンを例示しています。いずれもis_error: trueとtoolset_name: "browser"は共通で、contentの文言だけが変わります。
| ケース | 返すcontentの例 |
|---|---|
| スキーム拒否 | 返すcontentの例Error: Navigation refused. Only http and https URLs are allowed. |
| 古い・存在しない要素参照 | 返すcontentの例Error: ref_3 is stale or not found on the current page. Re-read the page to get fresh references. |
| 無効化・未実装のメンバー | 返すcontentの例Error: javascript_exec is not enabled in this environment. |
| バッチ内の後続呼び出し | 返すcontentの例Not executed: an earlier action in this turn failed.(文言固定) |
「無効化されたメンバー」は、configsで無効にしたメンバーをClaudeが呼んでしまったケースです。client toolsetsの仕様は、無効化したメンバーはClaudeに見えるツール一覧から除かれ、それでもClaudeが名指ししてきた場合はエラーのtool_resultを返すと定めています。「古い要素参照」は、executorが割り当てたref_2のような参照が、タブのナビゲーションやDOMの変化で無効になったときに起こります。参照を使い回さず、無効になった時点で明示的にエラーを返すのが正しい実装です。
バッチアクションは最初の失敗で打ち切る
1つのターンで複数のメンバー呼び出しが並ぶ「バッチアクション」では、失敗の伝播ルールが単発呼び出しと異なります。呼び出しは記載順に実行し、最初の失敗で止め、それ以降の呼び出しはすべてis_error: trueと固定文言Not executed: an earlier action in this turn failed.で答えます。実行しなかった呼び出しであっても、tool_result自体を省略することはできません。
検索ボックスをクリックし、文字を入力し、Enterキーを押す3つの呼び出しが1ターンにまとまっている場面を考えます。最初のクリックが古い参照エラーで失敗すると、続くtypeとkeyは実行されず、halt文言を持つエラー結果として返します。Claudeは3つの呼び出しを「クリックが成功した前提」で組み立てているため、実行しなかった呼び出しにも結果を返し、会話の整合性を保つ必要があります。
リクエストで実際に確認する
navigateにスキーム拒否のエラーを返す状況を、browser_toolset_20260801を宣言したMessages APIリクエストとして組むと次の形になります。
curl -sS https://api.anthropic.com/v1/messages \
-H "content-type: application/json" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "claude-opus-5",
"max_tokens": 1024,
"tools": [{"type": "browser_toolset_20260801"}],
"messages": [
{"role": "user", "content": "javascript:alert(1) を開いて"},
{"role": "assistant", "content": [
{"type": "tool_use", "id": "toolu_01LeUTyqkhRxBFq1QTG3pkwN",
"name": "navigate", "toolset_name": "browser",
"input": {"url": "javascript:alert(1)"}}
]},
{"role": "user", "content": [
{"type": "tool_result", "tool_use_id": "toolu_01LeUTyqkhRxBFq1QTG3pkwN",
"toolset_name": "browser", "is_error": true,
"content": "Error: Navigation refused. Only http and https URLs are allowed."}
]}
]
}'tool_resultにtoolset_name: "browser"を添えるのは、メンバー呼び出しに答える結果だけが持つ規約です。通常のカスタムツールへのtool_resultにはこのフィールドを付けません。この違いを取り違えると、単発のツールでは通っていた整形が、Browser use toolでは次に扱うリクエストエラーに変わります。
ダウンロード失敗はis_errorでは報告しない
すべての失敗がis_errorとcontentの組み合わせで表現されるわけではありません。クリックやナビゲーションがファイルダウンロードを開始し、そのダウンロードが失敗・キャンセルされた場合はdownload_failedという別の経路で報告します。これは成功した呼び出しのbrowser_stateブロックが持つstate_changes配列に載せるイベントの1種で、download_id・url・任意のerrorフィールドを持ちます。
ここで公式ドキュメントが釘を刺しているのが、is_error: trueの結果にstate_changesを送ってはいけないという規約です。ダウンロードの失敗がエラー呼び出しの最中に起きたとしても、そのstate_changesは当の結果には乗せず、次に成功した結果まで持ち越して報告します。browser_stateブロックそのものをis_error: trueの結果に付けないという規約と、この持ち越しルールは同じ原則の裏表です。download_id・url・path・errorの各フィールドには4,096文字・制御文字禁止という上限もあり、ブラウザが返す生のエラー文字列をそのまま転記する前に、この上限内へ整形しておく必要があります。
リクエスト自体が拒否される400エラー
executorが返すis_errorとは別に、tool_resultの形式そのものが規約に反すると、Claudeが応答する前にAPIがinvalid_request_errorで弾きます。整形ルール全般はtool_resultとtool_useの400エラーで扱った内容と地続きですが、executorのエラー処理を実装するうえでは、この2層を混同しないことが重要です。
| 何が起きているか | 原因 |
|---|---|
toolset_nameのechoが無い、または値が違う | 原因メンバー呼び出しの結果には、呼び出しと同じtoolset_nameを必ず添える |
text・image・browser_state以外のブロックを含む | 原因メンバー結果が許可されるブロック型はこの3種類のみ |
前ターンのメンバー呼び出しに対応するtool_resultが無い | 原因実行しなかった呼び出しにも結果を返す(バッチの後続呼び出しと同じ原則) |
new_tab・switch_tab・close_tab・list_tabsの結果がbrowser_stateブロック1つちょうどではない | 原因タブ管理系メンバーの結果はbrowser_stateブロック1つのみで構成する |
toolset_nameのechoは、成功結果にもエラー結果にも共通する規約です。一方browser_stateブロックは、is_error: trueの結果には付けてはいけません。タブの状態はエラー時には送らない、という非対称なルールです。
表に載るのはこの4行だけではありません。screenshotやzoomが返す画像がモデルの画像サイズ上限を超えている場合や、browser_toolset_20260801に対応していないモデルを指定した場合も、同じinvalid_request_errorで弾かれます。前者はAPIが画像を自動で縮小してくれないため、返す前にexecutor側でリサイズしておく実装が前提です。
Computer use toolとの共通点と違い
Browser use toolとComputer use toolはどちらもAnthropic定義のクライアントツールセットで、toolset_nameのechoやバッチアクションの停止規約など、エラー処理の骨格を共有しています。Computer Useツールを自前実装する最小構成で扱った実装パターンは、toolset_nameの値がcomputerかbrowserかを除けばそのまま流用できます。
差が出るのはbrowser_stateブロックの扱いです。これはブラウザのタブ状態を追跡するためにBrowser use toolだけが持つ仕組みで、Computer use toolの結果には登場しません。エラー結果からは常に省く、という規約さえ守れば、成功結果側のbrowser_state実装とは切り離して考えられます。
両ツールセットはscreenshotのようにメンバー名が重複することがあります。エラー結果を組み立てるtool_useを受け取ったら、nameだけでなくtoolset_nameとの組で判定し、どちらのツールセット宛のエラーかを取り違えないようにする実装が前提です。
対応モデルとプラットフォームの範囲
エラーハンドリングを実装する前提として、Browser use toolを呼べる環境そのものが限られています。対応モデルはclaude-fable-5-1・claude-mythos-5-1・claude-fable-5・claude-mythos-5・claude-opus-5・claude-sonnet-5・claude-opus-4-8の7つで、利用できるプラットフォームはClaude APIとGoogle Cloudの2つです。Claude Platform on AWS・Amazon Bedrock・Microsoft Foundryではこの日付付きツールセットを使えません。対応外のモデルを指定した場合は、executor側のエラーではなくAPI側のinvalid_request_errorとして返ってきます。
まとめ
Browser use toolのエラーハンドリングは、is_error: true・具体的なtext content・toolset_nameのecho・browser_stateの省略という基本形の上に、navigateのスキーム拒否とバッチアクションの停止という2つの個別規約が乗っています。スキーム拒否はURLパーサーでの判定を徹底し、バッチアクションは最初の失敗以降をすべてhalt文言で埋める。この2点を押さえたexecutor実装であれば、公式ドキュメントが定める規約の大部分を満たせます。
もう一段深い区分として、executorが返すis_errorと、APIが会話の前に弾くinvalid_request_errorは別レイヤーの失敗です。前者はtool_resultのis_errorでエラーを正しく伝える書き方で扱った一般的な文言設計の延長にあり、後者は並列ツール呼び出しが一部失敗したときのis_errorの返し方で触れたような整形ルールの延長にあります。両方を意識してexecutorを組むと、Browser use tool固有のエラーもそれ以外のツールと同じ土台で扱えます。