Repository navigation
Bind the site's dev and preview servers to IPv4 - #276
Merged
Merged
Conversation
`npm run preview` printed a URL that did not answer. The server was running,
but bound to the IPv6 loopback only:
TCP [::1]:4321 [::]:0 LISTENING 44248
http://[::1]:4321/ -> 200
http://127.0.0.1:4321/ -> 000 (connection refused)
Node 17 and later resolve a bare `localhost` IPv6-first, and Astro passes
that straight to `listen()`, so nothing was reachable over IPv4 -- which is
what a browser opening `http://localhost:4321` can end up trying, and what
every tool here that uses an explicit `127.0.0.1` was trying.
Both npm scripts now pass `--host 127.0.0.1`, which is what the two other
places in this repo that start these servers already do:
`.claude/launch.json` passes it to `astro dev`, and `scripts/a11y.mjs:163`
passes it to `astro preview`. The scripts a person runs by hand were the only
ones without it.
After: bound to `127.0.0.1:4321`, with both `127.0.0.1` and `localhost`
returning 200.
Worth knowing when debugging this again: the local wrapper around `astro
preview` daemonises it and returns immediately, and its `astro preview
status` reported "No preview server is running" while the process was alive
and listening. The bind address in `netstat -ano` is the thing to trust.
Contributor
|
Site preview: https://pr-276.netscli-site-preview.pages.dev Built from 75b114f with Production is unaffected: netscli.com is served from GitHub Pages via |
fstubner
added a commit
that referenced
this pull request
Aug 28, 2026
#276 made `npm run dev` and `npm run preview` pass `--host 127.0.0.1`. That was wrong, and it broke the thing it was meant to fix. Windows resolves `localhost` to the IPv6 loopback first: > ping -n 1 localhost Pinging Workstation [::1] with 32 bytes of data > node -e "dns.lookup('localhost',{all:true},...)" ::1 (IPv6), 127.0.0.1 (IPv4) So binding IPv4-only means a browser asking for `localhost` gets ERR_CONNECTION_REFUSED -- which is exactly what happened, in Edge, on the server I had just "fixed". Astro's default passes `localhost` to `listen()` and Node resolves it per-OS: `::1` on Windows, `127.0.0.1` on most Linux. That adapts to whatever the browser on that machine will ask for, which is the behaviour worth having. The original symptom was mine, not the repo's: my checks curled `127.0.0.1` while the server was on `::1`. The fix for that is to check `localhost` and let it resolve, not to pin the server to one family. Scripts that genuinely need a fixed address already pass their own -- scripts/a11y.mjs:163 and .claude/launch.json both do, and both are unaffected by this revert. Verified after reverting: a fresh `npm run preview` binds `[::1]:4321`, and `http://localhost:4321/` returns 200. The a11y gate still passes, 0 violations in both themes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
npm run previewprinted a URL that did not answer. The server was running — bound to the IPv6 loopback only:Node 17+ resolves a bare
localhostIPv6-first and Astro passes that straight tolisten(), so nothing was reachable over IPv4 — which is what a browser openinghttp://localhost:4321can end up trying, and what every tool here using an explicit127.0.0.1was trying.The repo already knew
Both other places that start these servers pass the flag:
.claude/launch.json→astro dev --host 127.0.0.1 --port 4322scripts/a11y.mjs:163→spawn(node, [astroCli, 'preview', '--host', host, ...]),hostdefaulting to127.0.0.1The two scripts a person runs by hand were the only ones without it. That is why the a11y gate has always worked while
npm run previewlooked broken.After
One thing that made this harder to see
The local wrapper around
astro previewdaemonises it and returns immediately, and its ownastro preview statusreported "No preview server is running" while the process was alive and listening on[::1]:4321. The bind address innetstat -anois the thing to trust, not the wrapper's status — noted in the commit message so the next person does not chase it.astro check0 errors · CSS budget 24 · changelog check · file-size guard.