Claude Media
Claude Codeのspawn E2BIGでBashツールが失敗する原因

Claude Codeのspawn E2BIGでBashツールが失敗する原因

Claude CodeのBashツールがspawn E2BIGで失敗する原因をGitHub Issueの実測から読み解き、サンドボックスのポリシー肥大化と回避策を解説します。

Claude Codeでサンドボックスを有効にしていると、コマンドの中身に関係なくBashツールがまるごと失敗することがあります。trueのような何もしないコマンドでも同じエラーが出ます。

Could not start /bin/zsh: the command line plus environment exceed the OS exec
argument limit (E2BIG). At spawn: command line 1.1MB across 3 args (largest
single arg 1.1MB); environment 4KB across 70 vars (largest: PATH at 1015 bytes).
The Bash sandbox profile adds 187 filesystem deny paths to every command.

原因はコマンド文字列の長さではありません。GitHub Issue #78253は、6つの作業ディレクトリを比較した実測から、失敗しているのはBashサンドボックスがコマンドごとに組み立てるファイルシステムポリシーそのものだと突き止めました。

Bashツールがspawn E2BIGで失敗する仕組み

Claude Codeはサンドボックス有効時、Bashを実行するたびにファイルシステムの許可・拒否ルールをコンパイルし、生成したポリシーを起動コマンドの引数として渡します。このポリシーが大きくなりすぎると、OSがプロセス起動時に許すコマンドライン+環境変数の合計サイズ(ARG_MAX)を超え、spawnシステムコールがE2BIGで失敗します。

報告されたエラーでは「187個のファイルシステム拒否パス」を含む約1〜1.1MBのポリシーが渡されており、これがそのまま引数上限超過の直接原因です。管理者が設定する組織全体のポリシー(managed settings)は、個人設定やプロジェクト設定の上に数百件規模のルールを積み増すため、素のインストールより上限に達しやすくなります。

なぜgitリポジトリの中だけで起きるのか

Issue報告者は、ワーキングツリーのファイル数が異なる6つの場所でBashツールを試し、次の結果を得ました。

場所gitリポジトリかワーキングツリーのファイル数(.git除く)結果
非gitの親ディレクトリgitリポジトリかいいえワーキングツリーのファイル数(.git除く)377,261結果成功
リポジトリA(本番設定リポジトリ)gitリポジトリかはいワーキングツリーのファイル数(.git除く)1,224結果失敗
リポジトリB(小規模な監視・自動化リポジトリ)gitリポジトリかはいワーキングツリーのファイル数(.git除く)148結果失敗
リポジトリC(依存関係の多いインフラプロジェクト)gitリポジトリかはいワーキングツリーのファイル数(.git除く)29,389結果失敗
リポジトリD(デプロイマニフェストリポジトリ)gitリポジトリかはいワーキングツリーのファイル数(.git除く)39,904結果失敗
初期化直後の最小リポジトリ(空コミット1つ)gitリポジトリかはいワーキングツリーのファイル数(.git除く)1結果成功

非gitディレクトリは37万ファイル超でも失敗しない一方、gitリポジトリでは148ファイル以上のワーキングツリーで例外なく失敗しています。単一ファイルのリポジトリは成功するため、条件は「cwdがgitリポジトリであること」と「ワーキングツリーが一定規模を超えていること」の両方が揃ったときに絞り込まれました。

原因はパターンの一致ではなく「数」

報告者はコマンド内容・gitのref数・.gitのreflogファイル数・.claude/commandsの有無・セッション履歴・秘密情報らしきファイル名との一致など、複数の仮説を個別に反証しています。reflogファイル数を大幅に減らしても失敗は再現し、秘密情報パターンに一致するファイル数は失敗する場所と成功する場所で相関しませんでした。

最終的に原因まで遡れたのは、失敗が始まる前夜に組織の管理ポリシーへ入った変更です。ファイル名に「secret」を含むものを広く拾う3個の部分一致パターンが、**/secret-values.yamlのような12個の拡張子指定パターンへ置き換えられ、ReadとEditの両方のルールに適用された結果、この変更単独で再帰パターンが正味18個増えました。同じリリースには非推奨になった権限動詞を使う約137件の古いルールを削除するクリーンアップも同梱されていたため、ルールの総数はむしろ減っています。

報告者は6箇所すべてで、新旧パターンがヒットするファイル数と成否の間に相関がないことも確認しました。この結果から報告者は、サンドボックスが**/から始まる再帰パターンをパターンごとに1回ワーキングツリー全体を走査しており、そのコストは一致の有無に関わらずツリーのサイズに比例する、という仮説を提示しています。パターンの実数が増えるほど、gitリポジトリ内で上限を超える確率が上がるという説明です。

git worktreeは小さいが確認済みの追加要因

リポジトリDの4回目のエラーメッセージだけは、拒否パス数を「187 → 190、うち3件は登録済みのgit worktreeに由来」と内訳付きで示しました。ワーキングツリー数が可視化された唯一の直接証拠です。

ただし報告者が別の2つのリポジトリでgit worktree listを確認したところ、いずれもworktreeは本体1つだけで追加はなく、それでも両方とも失敗しています。worktreeは実在する追加要因ですが、1MB超という超過幅に対して3エントリー分の寄与にとどまり、主要因ではありません。

サンドボックスの設定はプロセス単位で固定される

コンパイル済みのサンドボックスポリシーは、Claude Codeのプロセスが起動した時点で固定され、そのプロセスが生きている間は再計算されません。プロセス内で起動したサブエージェントにも同じ固定済みポリシーが引き継がれます。

報告者は稼働中のセッションに対してバージョンアップグレードとreflog削除の両方を試しましたが、どちらもそのセッションの失敗を止められませんでした。変更が反映されたのは、プロセスを完全に終了させて新規に起動し直した場合だけです。ポリシーの原因を設定変更やgit側のクリーンアップで取り除いても、同じセッション内で再試行するだけでは効果がないという点は、この不具合に対処するときに見落としやすい部分です。

回避策と、それぞれの限界

Issueで実測・提案された対処と、公式ドキュメントにある設定上の逃げ道を分けて示します。いずれも報告時点で正式な修正を代替するものではありません。

対策効果限界
個人設定の広い再帰allowグロブを削除する(Issue)効果個人設定側の再帰パターン数を減らせる(効果を実測した記録はない)限界組織管理ポリシー側の再帰パターンには個人設定から手が出せない
git worktree remove/git worktree pruneで不要なworktreeを片付け、Claude Codeを再起動する(Issue)効果拒否パスを数エントリー(実測3件)減らせる限界主要因のワーキングツリーサイズやパターン数には効かない
/sandboxパネルでそのセッションのサンドボックスを緩める(Issue)効果E2BIGを避けてコマンドを通せる限界サンドボックスの保護が及ばなくなる範囲が広がる
sandbox.filesystem.disabledでファイルシステム分離だけを外す(公式ドキュメント)効果ファイルシステム分離を外す設定(E2BIGを解消するかはIssue内で実測されていない)限界ユーザー設定・管理設定からのみ有効化でき、プロジェクト設定では効かない
ClaudeがdangerouslyDisableSandbox付きで自動リトライする既定のエスケープハッチ(公式ドキュメント)効果コマンド自体は成功する限界通常の権限フローに戻るため確認プロンプトが挟まるか、auto modeでは分類器の判定に委ねられる

worktreeの整理は次の手順で実測されています。整理した後は必ずClaude Codeを終了し、新規プロセスとして起動し直します。

git worktree list
git worktree remove <不要なworktreeのパス>
git worktree prune

sandbox.filesystem.disabledはユーザー設定または管理設定のsettings.jsonに書きます。ファイルシステム分離だけを外す設定で、ネットワーク隔離は維持されますが、これがE2BIGを解消するかどうかは公式ドキュメントにも記載がなく、Issue内でも実測されていません。

{
  "sandbox": {
    "filesystem": {
      "disabled": true
    }
  }
}

いずれの対策でも、変更を反映させるにはClaude Codeプロセスの再起動が前提になります。同一セッション内で設定だけ変えて再試行しても、サンドボックスの設定はプロセス単位で固定される節で見たとおり、固定済みのポリシーは更新されません。

同種の不具合とAnthropic側の対応状況

Issue #78253は、9月4日に自動クローズボット(github-actions[bot])によって「長期間動きがない」という理由で一方的にクローズされています。クローズのコメントは定型の自動応答で、Anthropic側が原因を特定・修正したことを示す言及は含まれていません。CHANGELOG(v2.1.283まで確認)にも、サンドボックスプロファイルの圧縮やE2BIG関連の修正に該当する記載は見当たりませんでした。Issue報告者自身が挙げた修正案の1つは、**/から始まる再帰パターンをパターンごとに走査するのではなく単一のツリー走査へ統合すること、もう1つは生成したパスリストをコマンドライン引数ではなく別チャネルで渡すことで、そもそもOSの引数上限と結び付けないことでした。どちらもコメント時点では実装の予定が明言されていません。

報告者は、同じspawn E2BIGのエラー文字列を持つ過去の別問題(#3836)は今回とは無関係だと明記しています。あちらはv1.0.54で発生した同日リグレッションで、v1.0.53へのロールバックで解決した別バグです。一方、Linux/WSL2固有の#74081とその未解決の前身である#46461は、根本原因は異なるものの同じ系統の問題だと位置付けられています。こちらはbubblewrapバックエンドが再帰的なRead(dir/**)拒否グロブを、一致したファイル1つにつき1つのbind引数へ展開してしまい、Linuxの引数上限を超えるという経路です。処理対象のファイルパス集合に比例してOSの引数上限を超えるという構造は共通しています。

コメント欄では、direnvのSessionStartフックを使っているユーザーに向けて、~/.claude/session-env/<session-id>配下のセッションファイルサイズを確認するようアドバイスも寄せられています。これは今回のサンドボックスポリシー膨張とは別の原因ですが、環境変数側からコマンドライン+環境変数の合計サイズを押し上げる、隣接した要因として言及されています。

同じくClaude Codeのサンドボックスヘルパーが起動直後に競合するタイミング依存の不具合はunshare(CLONE_NEWUSER)がClaude Codeのサンドボックスで失敗する原因、sandbox.excludedCommandsが意図どおりに効かない既知バグはsandbox.excludedCommandsが効かない3つの原因で扱っています。ファイルシステム分離だけを外す設定の詳細はsandbox.filesystem.disabledはファイルシステム分離だけ外す設定、サンドボックスが承認疲れを減らすためにどう設計されているかはClaude Codeのサンドボックス設計で扱っています。

まとめ

spawn E2BIGはコマンドの内容や設定ミスが原因ではなく、Bashサンドボックスがコマンドごとに組み立てるファイルシステムポリシーが、OSの引数上限を超えるまで膨らんでしまう不具合です。支配的な要因はgitリポジトリ内のワーキングツリーのファイル数で、これに組織の管理ポリシーや個人設定に含まれる再帰的な**/パターンの数が上乗せされます。git worktreeも拒否パスを数件増やす確認済みの要因ですが、寄与は小さめです。コンパイル済みのポリシーはプロセス単位で固定されるため、設定を直してもそのセッション内での再試行では反映されず、Claude Codeを新規プロセスとして起動し直す必要があります。Anthropic側による修正の明記は確認できておらず、個人設定の再帰パターンを減らす・worktreeを整理する・sandbox.filesystem.disabledでファイルシステム分離だけ外す、といった回避策を組み合わせて個別に対処する状態が続いています。管理ポリシー側の再帰パターン数そのものは開発者個人の設定変更では減らせないため、組織でClaude Codeを導入している場合は、この不具合が起きたらまず自分のワーキングツリーのファイル数とworktree構成を疑う前に、直近で管理ポリシーに追加された**/パターンの数を確認する方が近道になることがあります。

この記事を共有:XはてブLinkedIn