Error Handling in TypeScript
Scattering error responses through every handler guarantees inconsistency. Instead, throw typed errors in your handlers and translate them to problem+json in one place.
A typed error + a central handler
Section titled “A typed error + a central handler”flowchart LR H[Handler throws ApiError] --> M[Error middleware] M --> P[Map to problem+json] P --> R[Response with correct status]
Define an error type that carries the status and problem fields, then a single handler that converts it. Anything unexpected becomes a 500 — and you never leak a stack trace to the client.
Why centralize
Section titled “Why centralize”- Consistency — every error leaves through the same shape.
- Safety — unexpected errors become a generic
500; internals never leak. - Less code — handlers throw a line; they do not each build a response.
| Advantages (Centralized Error Handling) | Trade-offs |
|---|---|
| One consistent error shape across the API — no special cases | Setting up the middleware is upfront work |
| Prevents internal errors from leaking to the client | A bug in the error middleware can break every error response |
| All logging happens in one place — easy to monitor | Requires a well-designed error class hierarchy |
| Client-side retry logic behaves correctly | Custom error classes in TypeScript need care around transpilation |
Common mistakes
Section titled “Common mistakes”A try/catch in every controller Symptom:
- Every route handler has its own try/catch
- Error formats diverge — some routes send
{ error: "..." }, others{ message: "..." } - Use one central error middleware instead:
app.onError((err, c) => { ... })
Not logging the error before responding Symptom:
- The error handler sends a response without logging
- Production gets a
500with nothing to debug it with - Log the error with request context (userId, path, method) before sending the response
💡 Real-world examples
Hono (the framework this course uses):
app.onError((err, c) => { ... })— a global error handler- Handles every error type in one place
Express.js:
- A 4-parameter error middleware:
(err, req, res, next)- A centralized handler that logs to a monitoring system before responding is a common production pattern