Skip to content

πŸ› BUG: wrangler dev 100% CPU spin when IPv6 is disabled β€” Node.js binds [::1] but workerd resolves localhost to 127.0.0.1Β #12910

@hambergerpls

Description

@hambergerpls

Which Cloudflare product(s) does this pertain to?

Wrangler

What version(s) of the tool(s) are you using?

wrangler: 4.73.0 (also reproduced on 4.72.0)
workerd: 1.20260312.1 (also reproduced on 1.20260310.1)

What version of Node are you using?

22.22.0

What operating system and version are you using?

NixOS Linux (kernel 6.13.6)

Describe the Bug

Observed behavior

When IPv6 is disabled on the host network, wrangler dev starts and prints "Ready on http://localhost:8787" but never responds to any HTTP requests. The main workerd process immediately consumes 100% CPU and spins indefinitely. All endpoints (including static doc routes that don't touch any bindings) time out.

Debug logs (--log-level debug) show a tight infinite loop of:

exception = kj/async-io-unix.c++:1538: disconnected: connect(): Connection refused
uncaught exception; source = Uncaught (in promise); stack = Error: Network connection lost.

This repeats hundreds of times per second with no backoff, starving the workerd event loop so it cannot process any HTTP requests.

Root cause

The wrangler dev architecture uses two processes:

  • A Node.js process (wrangler CLI) that listens on an internal loopback port
  • A workerd process configured with --external-addr=loopback=localhost:<PORT>

The bug is an IPv4/IPv6 address mismatch between the two:

  1. Node.js binds its internal loopback port to [::1] (IPv6 only) β€” confirmed via ss -tlnp
  2. workerd resolves localhost to 127.0.0.1 (IPv4) first
  3. The IPv4 connection is refused (nothing listening on 127.0.0.1:<PORT>)
  4. workerd retries immediately in a tight loop with no backoff β†’ 100% CPU

Evidence:

# Node binds IPv6 only:
$ ss -tlnp | grep <PORT>
LISTEN 0  511  [::1]:<PORT>  [::]:*  users:(("node",pid=...,fd=...))

# IPv4 fails, IPv6 succeeds:
$ curl http://127.0.0.1:<PORT>/   β†’ exit 7 (connection refused)
$ curl http://[::1]:<PORT>/       β†’ exit 0 (success)

# workerd uses localhost which resolves to IPv4 first:
$ cat /proc/<workerd_pid>/cmdline | tr '\0' ' ' | grep -oP 'loopback=[^ ]+'
loopback=localhost:<PORT>

Expected behavior

wrangler dev should work correctly when IPv6 is disabled on the host. Specifically:

  1. Node.js and workerd should agree on the loopback address (both use 127.0.0.1, or use 0.0.0.0/dual-stack)
  2. If the loopback connection fails, workerd should implement exponential backoff instead of a tight retry loop
  3. Alternatively, wrangler should pass an explicit IP address (127.0.0.1) instead of localhost for --external-addr=loopback=

Workaround

Forcing Node.js to prefer IPv4 resolves the issue:

NODE_OPTIONS="--dns-result-order=ipv4first" wrangler dev

This makes Node.js bind to 127.0.0.1 instead of [::1], matching what workerd expects.

Steps to reproduce

  1. Disable IPv6 on your network interface (e.g., via NetworkManager, sysctl net.ipv6.conf.all.disable_ipv6=1, or router settings)
  2. Ensure /etc/hosts still has both 127.0.0.1 localhost and ::1 localhost (default on most distros)
  3. Create any Cloudflare Worker project with nodejs_compat enabled
  4. Run wrangler dev
  5. Try curl http://localhost:8787/ β€” it will hang indefinitely
  6. Check CPU: ps aux | grep workerd shows ~100% CPU usage

Related issues

Please provide any relevant error logs

Debug output (wrangler dev --log-level debug) shows the repeating pattern immediately at startup, before any HTTP request:

exception = kj/async-io-unix.c++:1538: disconnected: connect(): Connection refused
stack: ...workerd@4f45f62 ...workerd@4f461eb ...
uncaught exception; source = Uncaught (in promise); stack = Error: Network connection lost.
uncaught exception; exception = workerd/jsg/_virtual_includes/iterator/workerd/jsg/value.h:1480: disconnected: jsg.Error: Network connection lost.
stack: ...workerd@2cfbe50 ...workerd@2cfca8e ...

This pattern repeats hundreds of times per second with no backoff.

Environment details

wrangler: 4.73.0
workerd: 1.20260312.1
node: 22.22.0
bun: 1.3.9
OS: NixOS Linux, kernel 6.13.6
IPv6: disabled on network interfaces
/etc/hosts: both 127.0.0.1 and ::1 mapped to localhost

Metadata

Metadata

Labels

package:wranglerRelating to the `wrangler` package

Type

No type
No fields configured for issues without a type.

Projects

Status
Backlog

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions