Claude Codeのstale sandbox mask files警告を消す手順
claude doctorに出るStale sandbox mask files left by a killed sessionの原因と消し方です。SIGKILLで残った0バイトの読み取り専用ファイルをrmで外します。
Claude Codeのstale sandbox mask files警告を消す手順
Stale sandbox mask files left by a killed sessionは、強制終了されたセッションが残した空のファイルを知らせる警告です。消し方は、他のセッションを閉じてから、警告に出たパスをrmで消すだけです。
Claude Codeのclaude doctorに出ます。/statusにも同じ行が並びます。この記事では、警告が出る条件、残る仕組み、消す手順、消してはいけない場面を順に説明します。
この警告が出る環境と症状
警告が出るのは、LinuxとWSL2でサンドボックスが有効、かつファイルシステム分離がオンのときです。出る環境として挙がっているのはLinuxとWSL2だけで、macOSは含まれません。
困りごととして現れるのは、設定の保存失敗です。権限の確認ダイアログで「Yes, and don't ask again」を選んでも、選択が保存されません。原因は、設定ファイルがあるべき場所に、中身が空で読み取り専用のファイルが居座っているからです。
警告の本文は、次の形で出ます。パスはプロジェクトごとに変わります。
- Stale sandbox mask files left by a killed session: /home/you/project/.claude/settings.local.json
Fix: Remove each with `rm <path>` while no other Claude Code session is running in that project空のファイルが残る仕組み
サンドボックスは、まだ存在しないファイルへの書き込みを拒否したいとき、そこに0バイトの読み取り専用ファイルを作ります。コマンドの実行中だけ置き、終わったら消す動きです。
この後始末が走る前にセッションが落ちると、ファイルが残ります。例はSIGKILLです。
残ったファイルは、次のセッションの起動時に、また読み取り専用で束ねられます。つまり、放っておいても自然には消えません。起動のたびに保護が再適用されるため、保存の失敗も続きます。
警告が出るまでの流れ
- 1
コマンド実行中
存在しないファイルの上に、0バイトの読み取り専用ファイルが置かれます。
- 2
セッションが強制終了
後始末が走らず、ファイルが残ります。
- 3
次の起動
残ったファイルが読み取り専用で束ねられ、設定の書き込みが失敗します。
警告を消す手順
手順は4つです。どれも警告に書かれた内容に沿っています。
- 同じプロジェクトで動いている他のClaude Codeセッションをすべて終了する
- ターミナルで
claude doctorを実行し、警告に出たパスを控える - 控えたパスを
rmで1つずつ消す claude doctorをもう一度実行し、警告が消えたか確かめる
claude doctor
rm /home/you/project/.claude/settings.local.json
claude doctor警告に載るのは最大3件で、残りは件数だけが示されます。4件以上ある場合は、消してからclaude doctorを回し直し、警告が出なくなるまで繰り返します。
消したあとは、保存できていなかった権限の選択をやり直します。「Yes, and don't ask again」を選び直せば、設定ファイルが新しく作られます。
消す前に確かめること
他のセッションが同じプロジェクトで動いている間は、消してはいけません。そのセッションのサンドボックスが、同じ場所のファイルを使っている最中かもしれないからです。使用中のファイルは、そのセッションの書き込み保護の一部として働いています。消すと保護が外れます。
見分けのつかない場合は、次の順で確かめられます。
- 別のターミナルタブやtmux、リモート接続先でClaude Codeが動いていないかを見る
- 動いているものがあれば、保存中の作業を終えてから終了する
- 全部閉じたことを確かめてから、
rmを実行する
自分の環境で警告が出るかを確かめる
警告の条件は、プラットフォーム、サンドボックスの有効化、ファイルシステム分離の3つです。どれかが欠けていれば、この警告は関係ありません。
プラットフォームは、WSLの版で分かれます。PowerShellでwsl -l -vを実行して版を見ます。Sandboxing requires WSL2と出る場合はWSL1で動いており、サンドボックスが使えません。WSL2に上げるか、サンドボックスなしで使うことになります。ネイティブのWindowsでは、コマンドはサンドボックスなしで動きます。
LinuxとWSL2のサンドボックスは、bubblewrapとsocatに頼ります。足りないパッケージがあると、/sandboxのパネルにDependenciesタブが出ます。タブが出ていなければ、依存はそろっています。
sudo apt-get install bubblewrap socatFedora系はsudo dnf install bubblewrap socatです。コンテナの中でCan't mount proc on /newroot/proc: Operation not permittedのようなbwrapのエラーが出る場合は、原因が別です。この警告ではなく、enableWeakerNestedSandboxの話になります。
ファイルシステム分離がオンかどうかは、sandbox.filesystem.disabledで決まります。既定はfalseで、分離はオンです。trueにすると分離が外れ、ネットワークの制限だけが残ります。
空のファイルが居座りやすいパス
空のファイルが置かれるのは、「まだ存在しないファイル」の位置です。/sandboxのパネルでモードを選ぶと、設定は.claude/settings.local.jsonに保存されます。警告の例にこのファイルが出るのは、そのためだと考えられます。
サンドボックスが書き込みを禁じる保護対象のパスは、次の4つの場所にあります。
- 作業ディレクトリとその上位:
.claudeの設定ファイル、.claude/skills、.claude/agents、.claude/commands、.claude/hooks、.mcp.jsonなど - 作業ディレクトリだけ:
.bashrcや.zshrc、.gitconfig、.vscodeと.idea、.git内のhooksとconfig - bareリポジトリに見えてしまうファイル: 最上位の
HEAD、objects、refs ~/.claude(CLAUDE_CONFIG_DIRで変えている場合はそのディレクトリ)の大半と、~/.claude.json、.credentials.json
保護対象は、allowWriteで許可を足しても外れません。Editの許可ルールで覆っても同じです。外せる設定は、ファイルシステム分離ごと止めるfilesystem.disabledだけです。止め方はsandbox.filesystem.disabledの解説にあります。ただし分離ごと外すと全パスが無防備になるため、残った空ファイルを消す目的には合いません。
自分の環境で保護対象がどう展開されるかは、/sandboxを開いてConfigタブで確かめられます。「Denied within allowed」の欄に、denyWriteに書いた自分のエントリと並んで出ます。書き込み範囲の調整そのものは、allowWriteとdenyWriteの使い方が扱っています。
保護対象のパスにシンボリックリンクが現れた場合は、リンク先のファイルも次のコマンドから書き込み禁止になります。空のファイルとは別の仕組みですが、「設定が保存できない」という症状は似ます。
v2.1.257より前のバージョン
警告が出るようになったのはv2.1.257からです。それ以前のバージョンでも、強制終了で同じ空のファイルは残っていました。ただし、claude doctorは何も言いませんでした。
つまり、警告が出ないことは、ファイルが無い証拠になりません。v2.1.257より前のバージョンを使っていて、設定が保存されない場合は、次の2つを試せます。
claude updateで更新し、claude doctorに警告が出るかを見る- 保存先のディレクトリで、空のファイルが無いかを自分の目で探す
claude update
find .claude -maxdepth 1 -type f -size 02行目のfindは、.claude直下にある0バイトのファイルを列挙する補助です。見つかった中には、自分で作った空のファイルも混ざります。消す前に、本当にサンドボックスの残骸かを確認してください。
警告が出ないのに書き込みが失敗するとき
claude doctorが静かでも、サンドボックスの書き込み失敗は起こります。まず、サンドボックスが実際に効いているかを確かめます。Claudeにtouch ~/sandbox-probeを実行させ、LinuxとWSL2でRead-only file systemと返るかを見ます。自分でターミナルに打つ!プロンプトの実行は、サンドボックスの外で動くことが多く、検証になりません。もしtouchが成功してしまったら、~/sandbox-probeを消したうえで/sandboxを開き、サンドボックスの有効化と依存パッケージを見直します。
効いているのに特定のパスだけ書けない場合は、設定の置き場所も疑えます。管理者がallowUnsandboxedCommandsをfalseにしているなど、サンドボックスがadmin-requiredの状態だと、リポジトリの.claude/settings.jsonと.claude/settings.local.jsonに書いたfilesystem.allowWriteは無視されます。ユーザー設定の~/.claude/settings.jsonか管理設定に書けば反映されます。この場合、消すべき空のファイルは存在しないので、rmは効きません。
似た症状との切り分け
サンドボックスの書き込みエラーは、原因が複数あります。
| 症状 | 見る場所 |
|---|---|
| doctorにstale警告が出る、権限の保存が失敗する | 見る場所この記事。空ファイルをrmで消す |
git mergeがunable to unlink oldで失敗する | 見る場所保護パスやdenyWriteの下のファイルを置き換えようとしている |
| NixOSで権限エラーになる | 見る場所NixOSのサンドボックス権限エラー |
git mergeやgit checkoutがunable to unlink oldで失敗する場合、置き換えようとしているファイルは3か所のどれかにあります。保護対象のパス(.claude/skillsの下など)、denyWriteに書いたパスの下、サンドボックスが書き込みを許す範囲の外です。失敗のあと、Claudeがサンドボックスの外での再実行を提案することがあります。承認するか、別のターミナルでgitコマンドを自分で実行すれば進めます。allowUnsandboxedCommandsをfalseにしている場合は提案が出ないので、自分で実行します。
コンテナ内のbwrapエラーを直すenableWeakerNestedSandboxは、外側のコンテナがすでに必要な隔離を担っているときだけ使う設定です。有効にすると、新しい/procでは隠れるプロセス情報が、サンドボックス内のコマンドから見えます。
エラー文言がRead-only file systemで終わる点は、LinuxとWSL2で共通します。そのため文言だけでは区別できません。警告が出ているか、原因のパスが空のファイルかで切り分けます。
サンドボックスの起動方法そのものを見直したい場合は、sandbox-runtimeで起動する設定も参考になります。
まとめ
警告の正体は、強制終了で残った0バイトの読み取り専用ファイルです。他のセッションを閉じ、claude doctorで出たパスをrmで消し、警告が出なくなるまで繰り返します。権限の選択は、消したあとに選び直します。
警告が出ない古いバージョンでは、同じ残骸が黙って保存失敗を起こします。症状が当てはまるなら、更新してからclaude doctorで確かめるのが近道です。