An Expired JWT Caught by the File Upload Error Handler
TL;DR
- Expired admin JWTs produced a 500 with no log output at all, which made it nearly untraceable.
responses.serverErrorwas being called but never logging usefully.- The culprit was Multer’s error handler — meant for file uploads — catching the JWT error.
- It classified an auth failure as a server error, hence the misleading 500.
- Fixed by catching token errors in the JWT middleware first and letting unrelated errors pass through.
An expired JWT was failing silently. Server error status, no log line explaining it. Silent failures are the worst kind, because the absence of information is itself the only clue.
The investigation
I started at responses.serverError, narrowing down where it gets called, adding console logs and switching to a default logger to catch output. Nothing.
Postman showed the response status as “failure”, which sent me back through the server’s exported functions. Following that thread led somewhere I didn’t expect: Multer’s error handler, the middleware that exists for file upload errors.
The cause
JWT errors were being caught too late. By the time they surfaced, Multer’s handler — which has no business seeing them — picked them up and categorised them as server errors. Hence a 500 that told nobody anything, for what is really an ordinary expired-credential case.
That’s a middleware ordering problem wearing an authentication costume. Nothing about the JWT logic was wrong; the error just travelled further down the chain than it should have and got claimed by the first handler willing to take it.
The fix, and the one I avoided
The naive fix is to check for JWT errors inside Multer’s handler. That would work and it would be wrong — it teaches the file upload handler about authentication, and every future handler would need the same special case.
The right fix is to catch token errors in the JWT check middleware itself, before they can reach anything else:
- Token errors get caught in the JWT middleware, at the source.
- Errors that aren’t token errors pass through to subsequent middleware untouched.
- The JWT error middleware checks both error name and message to catch expired tokens comprehensively.
Outcome
JWT errors are handled where they belong and produce clear logs. The 500s are gone, replaced by responses that describe what actually happened.
The general lesson is about boundaries. In an Express chain, an error handler that’s too permissive will swallow things it doesn’t understand, and the symptom appears nowhere near the cause. Each handler should catch what it’s responsible for and decline everything else.
ryer.io