Error handling is one of those topics developers often ignore until production starts failing.
A good error-handling strategy makes an application easier to debug, monitor, and maintain.
The Problem With Random try/catch Blocks
You might see code like:
try {
await doSomething();
} catch (error) {
console.log(error);
}
This prevents an immediate crash, but it doesn't necessarily solve the problem.
What should happen next?
Should the API return 500?
Should the error be logged?
Should the request be retried?
Should the user receive a friendly message?
Centralized Error Handling
Express applications can use centralized middleware:
app.use((err, req, res, next) => {
console.error(err);
res.status(500).json({
message: "Something went wrong"
});
});
Application code can then pass errors to the middleware.
Separate Operational and Programming Errors
Not every error means the same thing.
An invalid request:
400 Bad Request
is very different from:
Database connection unexpectedly failed
The first may be expected.
The second might require immediate investigation.
Don't Leak Sensitive Information
Avoid returning:
{
"error": "MongoServerError: password authentication failed..."
}
to users.
Internal details belong in secure logs.
Users generally need a useful but safe message.
Logging Matters
A production system should record useful context:
- timestamp
- request ID
- endpoint
- user/session context where appropriate
- error type
- stack trace
A request ID is particularly useful when tracing one request through multiple services.
Final Thoughts
Good error handling isn't about hiding errors.
It's about making errors understandable, observable, and safe.
Top comments (0)