API Error Handling: Do It Right
Most APIs have terrible error handling. Here's how to build error responses that actually help developers.
The Problem
You hit an API and get back:
{ "error": "Something went wrong" }
Gee, thanks. Very helpful.
Good Error Responses
Include:
1. **Error code** - Machine-readable identifier 2. **Message** - Human-readable explanation 3. **Details** - What specifically failed 4. **Documentation link** - Where to learn more
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request body",
"details": [
{
"field": "email",
"issue": "must be a valid email address",
"received": "not-an-email"
}
],
"documentation": "https://api.example.com/docs/errors#VALIDATION_ERROR"
}
}
HTTP Status Codes Matter
Use them correctly:
- `400` - Client error, fix your request
- `401` - Not authenticated, log in
- `403` - Authenticated but not authorized
- `404` - Resource not found
- `422` - Validation failed
- `429` - Rate limited
- `500` - Server error, our fault
Implementation in Express
class AppError extends Error {
constructor(code, message, statusCode = 400, details = null) {
super(message);
this.code = code;
this.statusCode = statusCode;
this.details = details;
}
}
// Usage
throw new AppError(
'VALIDATION_ERROR',
'Invalid request body',
422,
[{ field: 'email', issue: 'required' }]
);
// Error handler middleware
app.use((err, req, res, next) => {
const statusCode = err.statusCode || 500;
res.status(statusCode).json({
error: {
code: err.code || 'INTERNAL_ERROR',
message: err.message,
details: err.details,
...(process.env.NODE_ENV === 'development' && { stack: err.stack })
}
});
});
Consistent Error Format
Every error, everywhere, same shape. Your API consumers will thank you.
Frontend can now:
try {
await api.createUser(data);
} catch (err) {
if (err.code === 'VALIDATION_ERROR') {
// Show field-specific errors
err.details.forEach(({ field, issue }) => {
showFieldError(field, issue);
});
} else {
// Generic error handling
showToast(err.message);
}
}
Predictable errors make for better developer experience.