Five checks in order
Read the startup terminal
Run the project’s documented development command. Use the exact Local URL it prints. Some tools select another port when 3000 is busy; others stop with an error.
Confirm the listener
# Windows PowerShell Get-NetTCPConnection -LocalPort 3000 -State Listen | Select-Object LocalAddress, OwningProcess # macOS or Linux lsof -nP -iTCP:3000 -sTCP:LISTENMake a direct HTTP request
curl -i http://127.0.0.1:3000/This separates network reachability from browser extensions, client JavaScript, and route rendering.
Check the intended route
If
/responds but/loginreturns 404, the port works. Check the framework’s route files and base path.Inspect browser and server logs together
A blank page with HTTP 200 usually needs the DevTools console and failed network requests, not a port change.
Use the exact error
| Error or result | What it establishes | Likely next step |
|---|---|---|
ERR_CONNECTION_REFUSED | The client could not open a connection. | Start the service; correct the port or bind address. |
EADDRINUSE | Node tried to bind an address already owned by another server. | Identify the existing PID or select another port. |
| HTTP 404 | A server answered the request. | Correct the application route or configured base path. |
| HTTP 500 | The app received the request and failed. | Read the server stack trace; fix the application error. |
| HTML shell, blank screen | Network and document request worked. | Check JavaScript exceptions, missing assets, and API calls. |
| Works in curl, not browser | The listener and basic HTTP response work. | Try a clean profile; inspect extensions, HTTPS upgrades, proxy, and cached service workers. |
Port 3000 is busy or wrong
Node documents EADDRINUSE as another server already occupying the requested address. Identify the owner before stopping it:
# Windows: show process details after finding OwningProcess
Get-Process -Id <PID>
# macOS or Linux: lsof output includes the command and PID
lsof -nP -iTCP:3000 -sTCP:LISTEN
For Next.js, choose a different port for one run:
next dev --port 3001
# package script form
npm run dev -- --port 3001
Next.js documents 3000 as its default. Vite defaults to 5173, so a Vite project should normally use the URL it prints rather than an assumed 3000 URL.
Root works, but /login or /admin does not
A path is not created by the port. Verify the exact framework route:
- For Next.js App Router, look for a matching segment such as
app/login/page.tsx. - For a client-side router, make sure the route is registered and the dev server returns the app shell on history fallback.
- For a backend endpoint, confirm the request method, API prefix, and whether the backend is actually on another port.
- For an authentication redirect, inspect the final URL and response chain instead of assuming the first path failed.
Docker and WSL
In Docker, both binding and publishing must be correct:
# Publish host 3000 to container 3000
docker run --rm -p 3000:3000 your-image
# Confirm the actual mapping
docker ps --format "table {{.Names}}\t{{.Ports}}"
The app inside the container usually needs to listen on 0.0.0.0. A process bound only to the container’s 127.0.0.1 is not reachable through the published port.
Windows can normally reach a server running inside WSL 2 at localhost. If the connection direction is reversed, or LAN access is required, check Microsoft’s current WSL networking model and the app’s bind address instead of copying an old IP workaround.
Binding to 0.0.0.0 expands access. Use it only when another network namespace or trusted LAN device needs the server, and keep firewall exposure narrow.
HTTP works, browser page fails
- Open DevTools Console and preserve the first exception.
- In Network, reload and find the first failed script, module, stylesheet, or API request.
- Compare
http://127.0.0.1:3000andhttp://localhost:3000only to diagnose address-family or proxy differences; fix the configuration rather than relying on a permanent mismatch. - Unregister a stale service worker only when DevTools shows it controlling the origin.
- Test a clean browser profile when an extension reports
ERR_BLOCKED_BY_CLIENT.
Official references
- Next.js CLIDevelopment command, default port, hostname, and port override.
- Node.js: Common system errorsDefinitions of EADDRINUSE and ECONNREFUSED.
- Vite: Server optionsWhy a Vite project usually prints 5173 and may choose another port.
- Microsoft: WSL networkingCurrent localhost forwarding, NAT, mirrored mode, and LAN considerations.
- Docker: Publishing portsHost and container port mapping.