Connection and application diagnosis

localhost:3000 not working

Do not start by clearing caches or changing the firewall. First determine whether the failure is at startup, TCP connection, HTTP response, application route, or browser rendering. Each layer has a different fix.

Next.js · Node · React dev serversWindows · macOS · Linux · WSL · DockerUpdated September 5, 2026
RefusedNo listener
EADDRINUSEPort occupied
HTTP 404Route problem
Blank screenClient/runtime

Five checks in order

  1. 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.

  2. Confirm the listener

    # Windows PowerShell
    Get-NetTCPConnection -LocalPort 3000 -State Listen |
      Select-Object LocalAddress, OwningProcess
    
    # macOS or Linux
    lsof -nP -iTCP:3000 -sTCP:LISTEN
  3. Make a direct HTTP request

    curl -i http://127.0.0.1:3000/

    This separates network reachability from browser extensions, client JavaScript, and route rendering.

  4. Check the intended route

    If / responds but /login returns 404, the port works. Check the framework’s route files and base path.

  5. 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 resultWhat it establishesLikely next step
ERR_CONNECTION_REFUSEDThe client could not open a connection.Start the service; correct the port or bind address.
EADDRINUSENode tried to bind an address already owned by another server.Identify the existing PID or select another port.
HTTP 404A server answered the request.Correct the application route or configured base path.
HTTP 500The app received the request and failed.Read the server stack trace; fix the application error.
HTML shell, blank screenNetwork and document request worked.Check JavaScript exceptions, missing assets, and API calls.
Works in curl, not browserThe 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

  1. Open DevTools Console and preserve the first exception.
  2. In Network, reload and find the first failed script, module, stylesheet, or API request.
  3. Compare http://127.0.0.1:3000 and http://localhost:3000 only to diagnose address-family or proxy differences; fix the configuration rather than relying on a permanent mismatch.
  4. Unregister a stale service worker only when DevTools shows it controlling the origin.
  5. Test a clean browser profile when an extension reports ERR_BLOCKED_BY_CLIENT.

Official references