Cannot GET / (Express / Node no matching route)
Express answered the HTTP request, but no route matched that method and path. The server is up — the URL is wrong or unregistered.
How it shows up
Cannot GET /
Cannot GET /api/users
Cannot POST /login
HTTP/1.1 404 Not Found
Content-Type: text/html; charset=utf-8
X-Powered-By: Express
You are past connect/TLS. curl gets a real HTTP response — just not the handler you expected.
What Express is saying
After the middleware stack runs, if nothing called res.send / next into a final handler, Express’s final handler sends a tiny HTML body: Cannot METHOD path. NestJS, some Fastify setups, and older Connect apps can print the same style of message.
vs lookalikes
| Symptom | Means |
|---|---|
| Cannot GET / | App up; no route for that method+path (404) |
| localhost refused to connect | Nothing listening on the port |
| EADDRINUSE | Your new process could not bind; old one may still be the one answering |
| 502 Bad Gateway | Proxy could not get a valid reply from upstream |
| 503 / 504 | Unavailable or gateway timeout — not a missing route |
| Blank SPA page / client router only | Server needs a fallback to index.html for client-side routes |
Common causes
- No route registered — forgot
app.get('/'), typo in path (/uservs/users), or router neverapp.use’d. - Wrong HTTP method — browser GET to a POST-only endpoint →
Cannot GET …. - Mount path —
app.use('/api', router)but you request/or/api/vs/apiinconsistently. - Static files not mounted — missing
express.static; asking for/app.jshits the 404 handler. - Reverse proxy path — nginx forwards
/api/foobut strips or doubles a prefix the app does not expect. - SPA deep link — user refreshes on
/dashboard; server has no such file/route. Need history-fallback toindex.html. - Listening on another process — old server without your new routes still bound (see EADDRINUSE).
Minimal fix patterns
import express from "express";
const app = express();
app.get("/", (_req, res) => res.send("ok"));
app.get("/api/health", (_req, res) => res.json({ ok: true }));
// JSON 404 instead of "Cannot GET …"
app.use((req, res) => {
res.status(404).json({ error: "not_found", path: req.path, method: req.method });
});
app.listen(3000, "127.0.0.1");
# Confirm what answers
curl -sI http://127.0.0.1:3000/
curl -s http://127.0.0.1:3000/missing
# List listeners if the wrong app might be up
ss -ltnp | grep 3000
SPA fallback (careful order)
app.use(express.static("dist"));
app.get("*", (req, res, next) => {
if (req.path.startsWith("/api")) return next();
res.sendFile("index.html", { root: "dist" });
});
// then API 404 / error handlers
Put API routes before the * fallback so /api/… still 404s as JSON when missing.
Checklist
- Log
req.method+req.originalUrlon a catch-all to see what arrived (proxy prefixes included). - Verify the router is mounted:
app.use('/api', apiRouter). - Match method and path exactly; trailing slashes matter unless you normalize them.
- Replace the default HTML 404 with JSON for APIs.
- If curl to the port works but the public URL 404s, fix the reverse-proxy
location/proxy_passpath.
Related
Invalid hook call (React) · localhost refused to connect · EADDRINUSE address already in use · 502 Bad Gateway · TypeError: Failed to fetch · CORS errors explained · Anvil HTTP status · Anvil URL inspect
Questions
What does Cannot GET / mean in Express?
Express received the request but no route matched that GET path, so it returned its default 404 HTML body.
Is the server down?
Usually no. Connection refused means down/wrong port. Cannot GET means the process answered with 404.
Why Cannot GET /api when my route exists?
Mount path, typo, trailing slash, wrong method (GET vs POST), or a reverse proxy rewriting the path differently than the app expects.
How do I change Cannot GET to JSON?
Add a final middleware that does res.status(404).json({ error: 'not_found' }) after all real routes.
Does this happen only in Express?
The exact phrase is classic Express, but any framework that returns a plain-text/HTML 404 for unknown routes can look similar.
Cannot GET on a React/Vue refresh?
Client-side routers need a server fallback to index.html for non-API paths; otherwise Express correctly says the file/route does not exist.
Published .