Skip to content

fix(miniflare): use 127.0.0.1 for internal loopback to prevent IPv6/IPv4 mismatch CPU spins#12913

Merged
petebacondarwin merged 3 commits intocloudflare:mainfrom
Sigmabrogz:fix/ipv6-localhost-spin
Apr 15, 2026
Merged

fix(miniflare): use 127.0.0.1 for internal loopback to prevent IPv6/IPv4 mismatch CPU spins#12913
petebacondarwin merged 3 commits intocloudflare:mainfrom
Sigmabrogz:fix/ipv6-localhost-spin

Conversation

@Sigmabrogz
Copy link
Copy Markdown
Contributor

@Sigmabrogz Sigmabrogz commented Mar 15, 2026

Describe your change...

Summary

This fixes the internal loopback communication between Node.js and workerd to prevent IPv6/IPv4 mismatch issues when `localhost` is configured.

Problem

When running `wrangler dev`, if the system has IPv6 disabled but `localhost` still maps to both IPv4 and IPv6 in `/etc/hosts` (the default on most distros), Node.js may bind the internal loopback port to `[::1]` (IPv6).

However, `workerd` resolves `localhost` to `127.0.0.1` (IPv4) first when constructing the `--external-addr=loopback=` parameter. This results in a connection refused error, and `workerd` attempts to reconnect immediately without backoff, causing 100% CPU usage.

Solution

Instead of changing the user-facing default IP (which could affect setups depending on `localhost`), this PR takes a more surgical approach:

  • Only the internal loopback communication in `packages/miniflare/src/index.ts` is modified
  • When `localhost` is configured, the internal loopback now uses `127.0.0.1` explicitly
  • The user-facing URL (shown in "Ready on...") remains `localhost` as before

This ensures both Node.js and workerd agree on the IPv4 loopback address for internal communication, while preserving the existing user-facing behavior.

Changes

  • `packages/miniflare/src/index.ts`:
    • `#getLoopbackPort()`: Use `127.0.0.1` instead of `localhost` for the loopback server
    • `#assembleAndUpdateConfig()`: Use `127.0.0.1` instead of `localhost` for the workerd external address

  • Tests
    • Tests included/updated
    • Automated tests not possible - manual testing has been completed as follows:
    • Additional testing not necessary because:
  • Public documentation
    • Cloudflare docs PR(s):
    • Documentation not necessary because: internal networking fix, no API changes

A picture of a cute animal (not mandatory, but encouraged)
cat

@Sigmabrogz Sigmabrogz requested review from a team as code owners March 15, 2026 14:19
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 15, 2026

🦋 Changeset detected

Latest commit: 824da61

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@workers-devprod
Copy link
Copy Markdown
Contributor

workers-devprod commented Mar 15, 2026

Codeowners approval required for this PR:

  • @cloudflare/wrangler
Show detailed file reviewers
  • packages/miniflare/src/index.ts: [@cloudflare/wrangler]
  • packages/miniflare/src/plugins/core/index.ts: [@cloudflare/wrangler]
  • packages/miniflare/src/plugins/shared/index.ts: [@cloudflare/wrangler]
  • packages/miniflare/test/index.spec.ts: [@cloudflare/wrangler]

devin-ai-integration[bot]

This comment was marked as resolved.

@Sigmabrogz
Copy link
Copy Markdown
Contributor Author

Thanks @devin-ai-integration! I've pushed a commit fixing the missed validation.ts assignment to 127.0.0.1 so it successfully transforms everything correctly across both and .

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Mar 16, 2026

create-cloudflare

npm i https://pkg.pr.new/create-cloudflare@12913

@cloudflare/kv-asset-handler

npm i https://pkg.pr.new/@cloudflare/kv-asset-handler@12913

miniflare

npm i https://pkg.pr.new/miniflare@12913

@cloudflare/pages-shared

npm i https://pkg.pr.new/@cloudflare/pages-shared@12913

@cloudflare/unenv-preset

npm i https://pkg.pr.new/@cloudflare/unenv-preset@12913

@cloudflare/vite-plugin

npm i https://pkg.pr.new/@cloudflare/vite-plugin@12913

@cloudflare/vitest-pool-workers

npm i https://pkg.pr.new/@cloudflare/vitest-pool-workers@12913

@cloudflare/workers-editor-shared

npm i https://pkg.pr.new/@cloudflare/workers-editor-shared@12913

wrangler

npm i https://pkg.pr.new/wrangler@12913

commit: 824da61

@edmundhung
Copy link
Copy Markdown
Member

Thanks for working on this. My main concern with this approach is that it changes the default public dev host from localhost to 127.0.0.1. That seems like it could affect setups that depend on the current localhost behavior.

My understanding is that the bug comes from the internal Miniflare/workerd communication using an ambiguous host. I wonder if it would be better to make that internal path use a concrete address while leaving the user-facing host unchanged. What do you think?

@Sigmabrogz Sigmabrogz force-pushed the fix/ipv6-localhost-spin branch from 9b61dc5 to 4324b73 Compare March 17, 2026 09:11
@Sigmabrogz
Copy link
Copy Markdown
Contributor Author

Thanks for the feedback @edmundhung! You're absolutely right - the original approach was too broad.

I've updated the PR to take a more surgical approach:

What changed:

  • Instead of changing the user-facing default IP, the fix now only affects the internal loopback communication between Node.js and workerd in packages/miniflare/src/index.ts
  • When localhost is configured, the internal loopback now uses 127.0.0.1 explicitly
  • The user-facing URL (shown in "Ready on...") remains localhost as before

Why this works:
The root cause is that Node.js may bind to [::1] (IPv6) when given localhost, while workerd resolves localhost to 127.0.0.1 (IPv4) first. By using 127.0.0.1 explicitly for the internal --external-addr=loopback= parameter, both processes agree on the same address.

Files changed:

  • packages/miniflare/src/index.ts - Two locations where the loopback host is computed

This approach:

  1. Fixes the CPU spin issue
  2. Preserves the existing user-facing behavior (localhost in URLs)
  3. Doesn't affect setups that depend on the current localhost behavior

Let me know if you'd like any adjustments!

@Sigmabrogz Sigmabrogz changed the title fix: set default dev IP to 127.0.0.1 instead of localhost to prevent CPU spins fix(miniflare): use 127.0.0.1 for internal loopback to prevent IPv6/IPv4 mismatch CPU spins Mar 17, 2026
@Sigmabrogz
Copy link
Copy Markdown
Contributor Author

@edmundhung I've added a changeset file as requested by the bot. The PR now includes:

  1. The surgical fix in packages/miniflare/src/index.ts - only affects internal loopback communication
  2. Changeset documenting the patch for miniflare

Ready for review when you have a moment. Thanks!

@edmundhung
Copy link
Copy Markdown
Member

@Sigmabrogz This is looking good, thanks! I just pushed a small follow-up to your branch to handle the module fallback service as well. Once I get another pair of eyes on this from my team, we should be in a good place to merge.

@edmundhung
Copy link
Copy Markdown
Member

@Sigmabrogz Can you please update the description following the PR Template? We have a CI check about that and fails because of that.

@Sigmabrogz
Copy link
Copy Markdown
Contributor Author

Updated the PR description to match the repo template so CI passes!

@workers-devprod
Copy link
Copy Markdown
Contributor

workers-devprod commented Apr 15, 2026

Codeowners approval required for this PR:

  • ✅ @cloudflare/wrangler
Show detailed file reviewers

@petebacondarwin petebacondarwin requested review from a team and petebacondarwin and removed request for a team April 15, 2026 06:54
Sigmabrogz and others added 3 commits April 15, 2026 12:12
… configured

This fixes the IPv6/IPv4 mismatch issue where Node.js binds to [::1] but
workerd resolves localhost to 127.0.0.1, causing a tight CPU spin loop.

The fix only affects the internal loopback communication between Node.js
and workerd, keeping the user-facing URL as localhost.

Fixes cloudflare#12910

Made-with: Cursor
@petebacondarwin petebacondarwin force-pushed the fix/ipv6-localhost-spin branch from adf19be to 824da61 Compare April 15, 2026 11:12
Comment thread .changeset/fix-ipv6-localhost-spin.md
Copy link
Copy Markdown
Contributor

@workers-devprod workers-devprod left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codeowners reviews satisfied

@github-project-automation github-project-automation bot moved this from Untriaged to Approved in workers-sdk Apr 15, 2026
@petebacondarwin petebacondarwin merged commit 7f50300 into cloudflare:main Apr 15, 2026
59 of 60 checks passed
@github-project-automation github-project-automation bot moved this from Approved to Done in workers-sdk Apr 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants