nestjs/nest · warning · NotFoundException
Cannot ${method} ${url}
Error message
Cannot ${method} ${url} What it means
This is the framework's built-in not-found handler: after route registration NestJS installs a catch-all callback that throws `NotFoundException('Cannot <method> <url>')` for any request no route matched, producing the standard 404 body. Seeing it means the router had no matching handler — which may be perfectly correct behavior, or a symptom that your routes/prefix/versioning are not registered the way you think.
Source
Thrown at packages/core/router/routes-resolver.ts:160
};
this.routerExplorer.explore(
instanceWrapper,
moduleName,
applicationRef,
host!,
routePathMetadata,
options,
);
});
});
}
public registerNotFoundHandler() {
const applicationRef = this.container.getHttpAdapterRef();
const callback = <TRequest, TResponse>(req: TRequest, res: TResponse) => {
const method = applicationRef.getRequestMethod(req);
const url = applicationRef.getRequestUrl(req);
throw new NotFoundException(`Cannot ${method} ${url}`);
};
const handler = this.routerExceptionsFilter.create({}, callback, undefined);
const proxy = this.routerProxy.createProxy(callback, handler);
const prefix = this.applicationConfig.getGlobalPrefix();
applicationRef.setNotFoundHandler &&
applicationRef.setNotFoundHandler(proxy, prefix);
}
public registerExceptionHandler() {
const callback = <TError, TRequest, TResponse>(
err: TError,
req: TRequest,
res: TResponse,
next: Function,
) => {
throw this.container.getHttpAdapterRef().mapException(err);
};
const handler = this.routerExceptionsFilter.create(View on GitHub (pinned to dd75d7bd8c)
Solutions
- Compare the exact URL and method against your registered routes (log them from the router or check the OpenAPI/Explorer output).
- Account for `setGlobalPrefix` and versioning in the URL you call.
- Make sure the controller class is declared in the module's `controllers` array and the module is imported.
- If the 404 is expected, keep it — or replace the default handler/exception mapping with a custom one for a better payload.
Example fix
// before: client calls /users but app uses prefix
await app.setGlobalPrefix('api');
// GET /users -> Cannot GET /users
// after
// GET /api/users -> 200
// or drop the prefix if the contract requires /users Defensive patterns
Strategy: fallback
Try / catch
// Map the default 404 to a useful payload for API consumers
import { Catch, NotFoundException, ExceptionFilter, ArgumentsHost } from '@nestjs/common';
@Catch(NotFoundException)
export class NotFoundFilter implements ExceptionFilter {
catch(_: NotFoundException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
ctx.getResponse().status(404).json({
statusCode: 404,
error: 'Not Found',
hint: 'Check the global prefix and route versioning (e.g. /api/v1/...)',
});
}
} Prevention
- Publish the OpenAPI spec so clients derive URLs from the app instead of hardcoding them.
- Cover global prefix + versioning in route smoke tests run against the started app.
- Add an explorability/health route at root to distinguish 'app up, path wrong' from 'app down'.
- Treat 404s as expected outcomes in clients and handle them explicitly rather than as errors.
When it happens
Trigger: Requesting a misspelled or missing path; a global prefix (set via `app.setGlobalPrefix('api')`) that the caller omitted or doubled; URI versioning enabled so the real path is `/v1/users` while `/users` 404s; the controller not being listed in its module's `controllers`; route params mismatching (e.g., `@Get('users/:id')` but requesting `/users/1/orders`) so the more specific path 404s.
Common situations: Frontend hardcoded paths drifting from backend routes after adding a global prefix; API consumers forgetting the version segment; proxy/gateway stripping or adding path prefixes; controllers forgotten in modules after refactors; HTTP method confusion (POST-only route hit with GET yields 404, not 405, since no route matches).
Related errors
- Conflicting HTTP routes detected: - ${messages} Adjust rou
- An invalid controller has been detected. "${className}" does
- HTTP adapter does not support filtering on host: "${host}"
- You must return an Observable stream to use Server-Sent Even
AI-assisted analysis of nestjs/nest@dd75d7bd8c (2026-08-21).
Data as JSON: /api/errors/a886abe65b6e1933.
Report an issue: GitHub.