Claude Code exits immediately under gVisor (regression from 2.1.42 to 2.1.49)

Resolved 💬 3 comments Opened Feb 20, 2026 by mikemott Closed Feb 24, 2026

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.0 and release-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

  1. Claude starts up normally (MCP servers connect, file indexing completes, REPL mounts)
  2. The welcome UI renders fully
  3. ~5 seconds after startup, the process exits with code 0
  4. No SessionEnd event is logged — the debug log just ends abruptly
  5. No signals received, no stderr output, no user input
  6. 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)
  • epoll on 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 -iouring flag (enabled io_uring syscall 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.

View original on GitHub ↗

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