Claude Code exits immediately under gVisor (regression from 2.1.42 to 2.1.49)
Summary
Claude Code exits cleanly (exit code 0) after ~5 seconds when running inside a Docker container using the gVisor (runsc) runtime. The REPL mounts but the process exits shortly after, before any user interaction. This is a regression — 2.1.42 works correctly under gVisor, 2.1.49 does not.
Environment
- Host OS: Ubuntu 24.04, kernel 6.8.0-100-generic
- Container: Docker with gVisor runtime (
runsc) - gVisor versions tested:
release-20260202.0andrelease-20260209.1(same result) - gVisor reported kernel:
Linux version 4.4.0 - Claude Code 2.1.42: Works — stays alive, REPL is interactive ✅
- Claude Code 2.1.49: Exits after ~5 seconds with code 0 ❌
- Same container image, same auth, same config — only Claude Code version differs
Behavior
- Claude starts up normally (MCP servers connect, file indexing completes, REPL mounts)
- The welcome UI renders fully
- ~5 seconds after startup, the process exits with code 0
- No
SessionEndevent is logged — the debug log just ends abruptly - No signals received, no stderr output, no user input
lastTotalInputTokens: 0— no API call is ever made
Root cause analysis
gVisor does not implement io_uring (returns ENOSYS). Bun (Claude's runtime) uses its own event loop based on io_uring on Linux and falls back to epoll. Something changed between 2.1.42 and 2.1.49 that causes the event loop to drain after startup tasks complete under gVisor's syscall emulation.
Confirmed not the cause:
- Terminal input (captured raw stdin — 0 bytes received)
epollon stdin (works correctly under gVisor, tested with Python)inotify(works correctly under gVisor)- Memory/OOM (container at 5% of 4GB limit)
- Signals (exit code 0, not >128)
- Auth/credentials (valid OAuth token, Claude Max subscription)
- Terminal size (73x58, adequate)
- gVisor's experimental
-iouringflag (enabledio_uringsyscall but did not fix the issue)
Confirmed by runtime comparison:
| Runtime | Claude 2.1.42 | Claude 2.1.49 |
|---------|--------------|--------------|
| runc (real kernel) | ✅ Works | ✅ Works |
| runsc (gVisor) | ✅ Works | ❌ Exits after ~5s |
Debug log pattern (2.1.49 under gVisor)
The last entries before exit are always background startup tasks completing:
[REPL:mount] REPL mounted, disabled=false
performStartupChecks called
...
AutoUpdaterWrapper: Installation type: native
Fast mode unavailable: ...
No exit event, no error — the log simply stops and the process exits with code 0.
Reproduction
# Create a gVisor container
docker run -d --runtime=runsc --name test -p 2222:22 ubuntu:24.04
# Install Claude Code 2.1.49 inside the container
# Authenticate with OAuth
# Run: claude
# Observe: UI appears, then exits after ~5 seconds
Workaround
Downgrading to Claude Code 2.1.42 resolves the issue under gVisor.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗