[BUG] claude-code 2.1.49+ exits on first tool call under gVisor (regression from 2.1.42)

Resolved 💬 3 comments Opened Apr 21, 2026 by igor-jerosimic-freemarket Closed May 27, 2026

Summary

Claude Code 2.1.49+ exits with code 0 on the first tool call (Bash, Read, Edit, etc.) when running inside a gVisor-based sandbox. Text-only prompts complete normally. 2.1.42 works end-to-end. The regression lives somewhere in the 2.1.42 → 2.1.49 range.

Previously reported in #27230 (duplicate of #12168); both are locked without a public resolution. Reopening with a reproducible test case and confirmed workaround.

Environment

  • Host: Windows 11 + Docker Desktop 4.69
  • Sandbox runtime: sbx v0.26.1 (standalone CLI), gVisor sentry (containerd-shim-nerdbox-v1)
  • Control (real kernel): same image under Docker Desktop's Moby VM + runc (via the docker sandbox extension)

Symptom

On gVisor, 2.1.49+ exits cleanly (code 0, no signal) the moment the model invokes a tool. Startup and text-only prompts complete normally.

Non-interactive reproducer:

# Works on 2.1.42 and 2.1.49+:
sbx exec <sandbox> -- claude --model sonnet -p "What is 2+2?"

# Works on 2.1.42, fails on 2.1.49+:
sbx exec <sandbox> -- claude --model sonnet --permission-mode acceptEdits \
  --output-format stream-json \
  -p "Use Bash: echo hello"

On 2.1.49+: stream-json events stop after the tool_use block, the sandbox transitions to stopped, exit code 0.
On 2.1.42: the same invocation returns {\"type\":\"result\",\"subtype\":\"success\",\"duration_ms\":11057,\"num_turns\":1} and exits cleanly.

Runtime matrix (tested)

| Runtime | 2.1.42 | 2.1.49+ |
|---------|--------|---------|
| runc / real Linux kernel (Moby VM, docker sandbox extension) | ✅ | ✅ |
| gVisor (sbx / nerdbox) | ✅ | ❌ exits on first tool call |

Only the kernel interface differs between the two rows — same image, same claude-code binary, same entrypoint.

Ruled out during testing

  • Auth/credentials — same credentials work for text-only prompts on 2.1.49+ and for full tool use on 2.1.42
  • OOM / memory pressure — container well within configured limits
  • Signal kill — exit code is 0, not >128

Workaround (verified)

Pin claude-code to 2.1.42:

RUN wget -qO \"/home/agent/.local/share/claude/versions/2.1.42\" \
      \"https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/2.1.42/linux-x64/claude\" \
    && chmod +x \"/home/agent/.local/share/claude/versions/2.1.42\" \
    && ln -sf \"/home/agent/.local/share/claude/versions/2.1.42\" ~/.local/bin/claude

Verified with multi-turn tool use (Bash → Read → Bash) and \stream-json\ completing with \\"subtype\":\"success\"\.

Ask

Identify the change between 2.1.42 and 2.1.49 that broke tool use under gVisor and restore the previous behaviour. gVisor is a common sandbox runtime (GKE Sandbox, standalone sbx, others), so the fix would unblock all of them.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗