[BUG] Windows sandbox breaks Gradle/JVM loopback IPC ("Unable to establish loopback connection") — still repros on 2.1.209 (#44857 closed without fix)

Open 💬 0 comments Opened Jul 14, 2026 by lranghetti

What's wrong

Any Gradle task (or any JVM tool that opens an NIO Selector) run from Claude Code's sandboxed Bash on Windows fails at JVM startup with Unable to establish loopback connection. ./gradlew --version works (it opens no Selector), but ./gradlew testDebugUnitTest / assembleDebug fail. The identical command in a normal terminal (outside the agent sandbox) works fine.

This is the same bug as #44857 (closed without a fix) and related to #18545 and #28018. Filing fresh because #44857 is closed and it still reproduces on the current release (2.1.209).

What should happen

Gradle/JVM/MCP tools should run inside the sandboxed Bash on Windows — the agent should be able to build/test Android & JVM projects, as it can in a normal terminal.

Error Messages/Logs

> ./gradlew testDebugUnitTest
FAILURE: Build failed with an exception.
* What went wrong:
java.io.IOException: Unable to establish loopback connection
    at java.base/sun.nio.ch.WEPollSelectorImpl.<init>(Unknown Source)
    at java.base/sun.nio.ch.WEPollSelectorProvider.openSelector(Unknown Source)
Caused by: java.net.SocketException: Invalid argument: connect
    at java.base/sun.nio.ch.UnixDomainSockets.connect0(Native Method)
    at java.base/sun.nio.ch.UnixDomainSockets.connect(Unknown Source)
    at java.base/sun.nio.ch.SocketChannelImpl.connect(Unknown Source)
    at java.base/sun.nio.ch.PipeImpl$Initializer$LoopbackConnector.run(Unknown Source)

Steps to Reproduce

  1. On Windows, in any Android/Gradle project (JDK 17+, e.g. the Android Studio JBR), from Claude Code's Bash tool run: ./gradlew testDebugUnitTest.
  2. It fails at JVM startup with the loopback IOException above.
  3. ./gradlew --version succeeds (no NIO Selector is opened, so no AF_UNIX socket).
  4. The same command in a normal PowerShell/Git Bash terminal → BUILD SUCCESSFUL.

Root cause (credit to the analysis in #44857): JDK 17+ on Windows uses WEPollSelectorImpl, which opens an AF_UNIX socket for its wakeup pipe. The socket path derives from %TEMP%, and Windows caps sockaddr_un.sun_path at 108 bytes. Inside the sandbox the effective path exceeds 108 → EINVAL. This happens even when %TEMP% looks short — mine was C:\Users\<user>\AppData\Local\Temp (~38 chars) and it still failed, so the sandbox's path handling pushes the effective socket path over the limit.

Workaround that works (confirms it's a hard blocker, not user error)

  1. settings.json: "sandbox": { "filesystem": { "allowWrite": ["C:\jtmp"] } }
  2. mkdir C:\jtmp
  3. Force a very short TEMP for the child process: export TEMP='C:\jtmp' TMP='C:\jtmp' && ./gradlew testDebugUnitTestBUILD SUCCESSFUL (28/28 unit tests ran).

Note: setting TMP/TEMP via settings.json env does not work (overridden), and ~/.bashrc is not sourced by the Bash tool — the only thing that worked was forcing TEMP inline on the command plus the sandbox allowWrite above.

Environment

  • Claude Code version: 2.1.209 (Windows desktop)
  • OS: Windows 11
  • Terminal/Shell: Claude Code's sandboxed Bash tool (MSYS/Git Bash)
  • JDK: 21 (Android Studio JBR), Gradle 8.5
  • Regression: Yes — reported as a regression in #44857 (which was on 1.2.234); still broken on 2.1.209. Exact last-working version unknown (already broken at 1.2.234).

Suggested fix

Provide child processes a short, sandbox-managed TEMP/TMP (or avoid leaking the long/virtualized path into %TEMP%), so JVM WEPollSelectorImpl can create its AF_UNIX wakeup socket within the 108-byte sun_path limit. This unblocks Gradle, plain java, and MCP servers on Windows.

View original on GitHub ↗