Native update/install fails with 'socket connection was closed unexpectedly' behind proxy — undici TLS incompatibility

Open 💬 2 comments Opened May 28, 2026 by RS-Nocsi

Description

claude update and claude install consistently fail with:

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

This occurs when running behind a proxy (system proxy enabled). The issue is specific to the bundled undici fetch() inside claude.exe — all other methods of accessing the same URL work fine.

Environment

  • OS: Windows 11
  • Claude Code version: 2.1.153 (native install)
  • System Node.js: v24.15.0
  • Proxy: HTTP/HTTPS proxy on localhost

Reproduction

  1. Run behind a proxy
  2. Execute claude update or claude install
  3. Fails immediately with the socket error

What works vs. what doesn't

| Method | Result |
|--------|--------|
| Browser access to downloads.claude.ai | ✅ Works |
| curl https://downloads.claude.ai/claude-code-releases/latest | ✅ Works |
| Node.js https.get() (system Node v24) | ✅ Works |
| Node.js fetch() (system Node v24) | ✅ Works |
| claude.exe internal fetch() (bundled Node) | ❌ Fails |

Root cause analysis

The TLS handshake fails specifically inside the bundled undici in claude.exe. This was confirmed by:

# System Node.js fetch works fine
node -e "fetch('https://downloads.claude.ai/claude-code-releases/latest').then(r => r.text()).then(console.log)"
# Output: 2.1.153 ✅

# But claude.exe fails on the same URL
claude update
# Error: socket connection was closed unexpectedly ❌

Setting NODE_TLS_REJECT_UNAUTHORIZED=0 does not resolve the issue for claude.exe, suggesting the problem is deeper than certificate validation — likely an incompatibility between the bundled undici version's TLS implementation and certain proxy configurations.

Additional context

  • The same claude.exe version (2.1.153) works on one machine but fails on another with the same system Node.js version (v24.15.0), suggesting the bundled Node.js/undici version may differ or there's a subtle environmental difference in how the binary interacts with the proxy.
  • Related issues: #60133 (SO_KEEPALIVE analysis), #37801 (update fails but curl works), #13498 (GCS timeout)

Suggestion

Consider adding proxy support to the native updater (respecting HTTP_PROXY/HTTPS_PROXY environment variables) or falling back to https.get when fetch() fails.

View original on GitHub ↗

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