Error message
UnauthorizedError: No authorization token was found
Also printed as
- No authorization token was found
- Format is Authorization: Bearer [token]
Unhandled, Express prints the error with its stack, starting with "UnauthorizedError: No authorization token was found". `err.code` distinguishes `credentials_required` (no token) from `credentials_bad_scheme` and `credentials_bad_format` ("Format is Authorization: Bearer [token]").
express-jwt (Node.js) — UnauthorizedError, code credentials_required
What it means
express-jwt protects the route but found no token: the request has no `Authorization` header and no custom `getToken` function returned one. Because `credentialsRequired` defaults to `true`, the middleware raises `UnauthorizedError` with `code: "credentials_required"` and `status: 401`, and the request never reaches your handler. A header that is present but not of the form `Bearer <token>` fails with "Format is Authorization: Bearer [token]" instead.
Why it happens
The client sent no Authorization header
commonNot logged in yet, an HTTP client without the interceptor that adds the header, or a token that was cleared after expiry. Check the request in the browser's network panel.
The token travels in a cookie or query string
commonexpress-jwt reads only `Authorization: Bearer` by default. Tokens in an HttpOnly cookie, a `?access_token=` parameter or a custom header need a `getToken` function — and cookies also need `cookie-parser`.
A proxy removed the header
occasionalAPI gateways with explicit header mappings, proxies that forward only an allow-list of headers, or a rewrite rule that clears the header can drop `Authorization` before the request reaches Node. The browser shows the header; the server never receives it.
The middleware also guards public routes
occasional`app.use(expressjwt(...))` before the routes protects everything, including health checks, login and static assets. Requests to those routes legitimately carry no token.
How to fix it
- 1.
Tell express-jwt where the token is
`getToken` receives the request and returns the token string or `null`. Keep it simple and avoid accepting tokens from several places at once.
js import cookieParser from "cookie-parser"; import { expressjwt } from "express-jwt"; app.use(cookieParser()); app.use( expressjwt({ secret: getSigningKey, // e.g. jwks-rsa's expressJwtSecret(...) algorithms: ["RS256"], getToken: (req) => req.cookies.access_token ?? null, }), ); - 2.
Exempt public routes, or make authentication optional
`.unless()` skips listed paths. `credentialsRequired: false` lets requests without a token through with no `req.auth`, so each route can decide.
js app.use( expressjwt({ secret, algorithms: ["HS256"] }).unless({ path: ["/health", "/login", /^\/public\//] }), ); // Or keep authentication optional and decide per route: app.use(expressjwt({ secret, algorithms: ["HS256"], credentialsRequired: false })); - 3.
Turn the error into a proper 401
Express's default handler uses the error's `status` (401) but answers with an HTML page — including the stack trace in development — and no `WWW-Authenticate` header. Map `UnauthorizedError` to a JSON 401 with that header yourself.
js app.use((err, req, res, next) => { if (err.name === "UnauthorizedError") { return res.status(401).set("WWW-Authenticate", "Bearer").json({ error: err.code }); } next(err); });