Summary
On macOS, Claude Code 2.1.120 refuses to start a resumed session, exiting with:
Error: sandbox required but unavailable: <reason>
sandbox.failIfUnavailable is set — refusing to start without a working sandbox.
The same machine on 2.1.119 resumes the same sessions cleanly. Fresh (non-resumed) sessions on 2.1.120 also work — only --continue and --resume are affected.
~/.claude/settings.json already has the documented escape hatch:
"sandbox": {
"enabled": false,
"failIfUnavailable": false
}
…and the error still fires on 2.1.120 resumes. With sandbox.enabled = false, isSandboxRequired() should short-circuit to false in both versions (verified by inspecting the binaries — see below), so the user-facing settings are not actually suppressing the resume-path check in 2.1.120.
Reproduction
# Works on 2.1.120
claude # fresh session, fine
claude --print "hi" # fine
# Fails on 2.1.120
claude --continue # → "No deferred tool marker found ..."
claude --continue "continue" # → sandbox-required error
claude --resume <session-id> "x" # → sandbox-required error
# Same commands on 2.1.119: all work
/path/to/versions/2.1.119 --continue "continue" # OK
Settings file is valid JSON, no managed-settings layer present (/Library/Application Support/ClaudeCode/, ~/Library/Application Support/ClaudeCode/, /etc/claude-code/ all absent), no relevant env vars set, sandbox-exec exists at /usr/bin/sandbox-exec, SIP enabled (default).
What the binaries show
Both 2.1.119 and 2.1.120 have functionally equivalent gates:
// 2.1.120 (minified)
function y7_() { return l8()?.sandbox?.enabled ?? false } // sandbox.enabled
function uc_() { /* platform allowed list — true if no policy restricts */ }
function bZ1() { return y7_() && uc_() && (l8()?.sandbox?.failIfUnavailable ?? false) } // isSandboxRequired
Identical call counts on both versions:
getSandboxUnavailableReason(): 4
isSandboxRequired(): 4
isSandboxingEnabled(): 50
isSandboxEnabledInSettings(): 6
So the gating logic is unchanged. The regression appears to be in when/where the resume code path consults the gate — 2.1.120 surfaces the unavailability before the user's sandbox.enabled = false is honored on resume specifically.
Environment
- Claude Code: 2.1.120 (failing) vs 2.1.119 (working)
- Platform: macOS Darwin 25.2.0, arm64
- Binary:
/Users/<user>/.local/share/claude/versions/2.1.120 (Mach-O arm64, Bun-bundled)
- Shell: zsh
csrutil: enabled
which sandbox-exec: /usr/bin/sandbox-exec
Workaround
Pin to 2.1.119:
ln -sf ~/.local/share/claude/versions/2.1.119 ~/.local/bin/claude
Asks
- The actual
<reason> returned by getSandboxUnavailableReason() on the failing machine would be the most useful next data point — currently the value is truncated in the user-facing error before the line wraps. Could the error printer be tweaked to always print the reason on its own line / not truncate it?
- Honor
sandbox.enabled = false consistently on the resume code path (it appears to be honored for fresh and --print invocations but not for --continue/--resume in 2.1.120).
- Separately,
claude --continue (no prompt) on 2.1.120 errors with No deferred tool marker found in the resumed session. whenever the prior session ended cleanly — the message tells you to "Provide a prompt", which works, but the bare --continue UX is now broken for any session that didn't end mid-deferred-tool.
Summary
On macOS, Claude Code 2.1.120 refuses to start a resumed session, exiting with:
The same machine on 2.1.119 resumes the same sessions cleanly. Fresh (non-resumed) sessions on 2.1.120 also work — only
--continueand--resumeare affected.~/.claude/settings.jsonalready has the documented escape hatch:…and the error still fires on 2.1.120 resumes. With
sandbox.enabled = false,isSandboxRequired()should short-circuit to false in both versions (verified by inspecting the binaries — see below), so the user-facing settings are not actually suppressing the resume-path check in 2.1.120.Reproduction
Settings file is valid JSON, no managed-settings layer present (
/Library/Application Support/ClaudeCode/,~/Library/Application Support/ClaudeCode/,/etc/claude-code/all absent), no relevant env vars set,sandbox-execexists at/usr/bin/sandbox-exec, SIP enabled (default).What the binaries show
Both 2.1.119 and 2.1.120 have functionally equivalent gates:
Identical call counts on both versions:
getSandboxUnavailableReason(): 4isSandboxRequired(): 4isSandboxingEnabled(): 50isSandboxEnabledInSettings(): 6So the gating logic is unchanged. The regression appears to be in when/where the resume code path consults the gate — 2.1.120 surfaces the unavailability before the user's
sandbox.enabled = falseis honored on resume specifically.Environment
/Users/<user>/.local/share/claude/versions/2.1.120(Mach-O arm64, Bun-bundled)csrutil: enabledwhich sandbox-exec:/usr/bin/sandbox-execWorkaround
Pin to 2.1.119:
Asks
<reason>returned bygetSandboxUnavailableReason()on the failing machine would be the most useful next data point — currently the value is truncated in the user-facing error before the line wraps. Could the error printer be tweaked to always print the reason on its own line / not truncate it?sandbox.enabled = falseconsistently on the resume code path (it appears to be honored for fresh and--printinvocations but not for--continue/--resumein 2.1.120).claude --continue(no prompt) on 2.1.120 errors withNo deferred tool marker found in the resumed session.whenever the prior session ended cleanly — the message tells you to "Provide a prompt", which works, but the bare--continueUX is now broken for any session that didn't end mid-deferred-tool.