[BUG] Same-cwd concurrent Claude Code sessions trigger persistent ECONNRESET / socket closed

Resolved 💬 3 comments Opened Apr 21, 2026 by Weldon0 Closed May 28, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Running two or more concurrent long-lived Claude Code sessions with the same cwd triggers persistent socket connection was closed unexpectedly / ECONNRESET errors. Once the errors start, they continue indefinitely — built-in retries cannot recover.

This happens regardless of how the instances are started:

  • Two terminal claude instances in the same directory
  • VS Code Claude Code extension + terminal claude in the same directory
  • Any combination of CLI / IDE / desktop app pointing at the same working directory

The failure mode is 100% reproducible on my machine and 100% resolved by killing one of the instances (the surviving instance recovers immediately, with no other config change).

Typical error from affected sessions:

API Error: The socket connection was closed unexpectedly.
For more information, pass verbose: true in the second argument to fetch()

curl to api.anthropic.com via the same proxy / network path continues to return HTTP 405 in ~1s throughout — the network path is healthy.

What Should Happen?

Either of the following:

  1. Session isolation (ideal): Each Claude Code process should use a session-scoped state directory (e.g., by session UUID) rather than sharing ~/.claude/projects/<cwd-hash>/ and ~/.claude.json across all instances with the same cwd. This is already tracked as #24864.
  1. At minimum — warn and refuse: When a second claude process is launched in a directory that already has an active session, it should warn (or refuse to start) — similar to how git prevents concurrent rebase/merge in the same repo.
  1. Or — surface the real error: If the issue is downstream corruption of shared state, the resulting failure should not masquerade as a generic network ECONNRESET. A clearer error message ("shared session state is inconsistent; another instance may be running in this directory") would save users hours of chasing phantom network issues.

Error Messages/Logs

API Error: The socket connection was closed unexpectedly.
For more information, pass verbose: true in the second argument to fetch()

Steps to Reproduce

  1. Open two terminal windows, both cd to the same project directory /path/to/projectA.
  2. In terminal 1, run claude (Instance A, cwd = /path/to/projectA).
  3. In terminal 2, run claude (Instance B, same cwd).
  4. Start a long-running task in either instance (multi-minute tool use, large file edits, or a long streaming response).
  5. Within a few minutes, both sessions start emitting API Error: The socket connection was closed unexpectedly repeatedly. Built-in retries (11 attempts, exponential backoff) never recover.

Note: Replacing terminal 2 with the VS Code Claude Code extension reproduces the same way. The trigger is same-cwd concurrency, not which frontend launches the process.

The critical test that identified the cause:

  • kill -9 <PID of Instance B> → Instance A recovers instantly, completes its task without further errors.
  • Inverse also works (killing A unblocks B).
  • Running two instances in different directories (or via git worktree) — no failure, even for hours.
  • Running a single instance in the same directory — no failure.

What I ruled out (spent ~8 hours testing, none of these changed the behavior while both instances were live):

  • Turning Clash.Meta TUN mode off / on
  • Switching proxy software (ClashX Meta → Surge)
  • Switching proxy protocol (SOCKS5 → HTTP CONNECT)
  • macOS TCP keep-alive tuning (net.inet.tcp.keepidle, always_keepalive)
  • Lowering Wi-Fi MTU from 1500 → 1492
  • Clearing stale utun interfaces
  • Setting CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1, DISABLE_NON_ESSENTIAL_MODEL_CALLS=1, CLAUDE_STREAM_IDLE_TIMEOUT_MS=600000, API_TIMEOUT_MS=1800000
  • Raw curl to api.anthropic.com via the same proxy: always succeeded (HTTP 405, ~1s) during the entire failure window

As soon as a second same-cwd instance was killed, failures stopped instantly — no other change needed.

Claude Model

None

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.1.116 (bundled Bun runtime)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

Hypothesis

Two instances share the following state files:

  • ~/.claude/projects/<hash>/sessions-index.json
  • ~/.claude.json (see #25768, #27311 for confirmed concurrent-write issues)
  • .claude/plans/ plan files (#27311)

Concurrent reads/writes likely produce inconsistent state. Something downstream (undici connection pool, internal telemetry/session sync, or retry logic) observes that state and gives up on sockets — surfacing as ECONNRESET while the network is actually fine.

This would explain why #23081 (stale HTTP/2 pool) reproduces intermittently for some users and is hard to trigger with clean single-session tests.

Related / possibly connected

  • #23081 (locked) — same error text, stale HTTP/2 connection pool
  • #48008 — ECONNRESET on streaming (macOS arm64)
  • #24864 — Session isolation feature request
  • #27311 — Plan files overwritten across concurrent sessions
  • #25768 — .claude.json concurrent write (EBUSY on Windows)
  • #5674 — Persistent ECONNRESET on macOS

Current workaround

  • One Claude Code instance per directory, period.
  • For parallel work: git worktree add ../proj-taskB feature-b, then run the second claude in the new worktree directory.
  • If running VS Code extension + terminal claude on the same repo: disable one of them.

Environment

  • OS: macOS (Apple Silicon)
  • Network: Local HTTP proxy (also reproduced across SOCKS5 / HTTP CONNECT / different proxy software)

View original on GitHub ↗

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