Restful Error Responses
title: "RESTful Error Responses — Consistent Error Format for REST APIs" description: "RESTful error responses follow a consistent JSON structure with error code, message, details, and request ID, making error handling predictable for all API clients." date: 2026-06-28 lastmod: 2026-06-28 weight: 18 tags: [apis, restful] }
RESTful error responses use a consistent JSON envelope with error code, human-readable message, detailed validation errors, and request ID for debugging.
What You'll Learn
- Standard error response format
- Error categorization
- Producing actionable error messages
Why It Matters
Consistent error responses let clients write generic error handling. Inconsistent errors force case-by-case handling and frustrate developers.
Error Response Format
// Standard error response structure
{
"error": {
"code": "VALIDATION_ERROR",
"message": "The request body contains invalid fields.",
"details": [
{
"field": "email",
"message": "Must be a valid email address",
"code": "INVALID_FORMAT"
},
{
"field": "age",
"message": "Must be a positive integer",
"code": "INVALID_VALUE"
}
],
"request_id": "req-abc123",
"documentation_url": "https://docs.example.com/errors#VALIDATION_ERROR"
}
}
Code Examples
class APIException(Exception):
def __init__(self, status_code, code, message, details=None):
self.status_code = status_code
self.code = code
self.message = message
self.details = details or []
@app.errorhandler(APIException)
def handle_api_error(error):
response = jsonify({
"error": {
"code": error.code,
"message": error.message,
"details": error.details,
"request_id": getattr(request, 'request_id', ''),
"documentation_url": f"https://docs.example.com/errors#{error.code}"
}
})
response.status_code = error.status_code
return response
@app.route('/users', methods=['POST'])
def create_user():
data = request.json
errors = []
if not data.get('name'):
errors.append({
"field": "name",
"message": "Name is required",
"code": "REQUIRED"
})
if data.get('email') and '@' not in data['email']:
errors.append({
"field": "email",
"message": "Must be a valid email address",
"code": "INVALID_FORMAT"
})
if errors:
raise APIException(422, 'VALIDATION_ERROR',
'The request body contains invalid fields.', errors)
user = db.create_user(data)
return jsonify(user.to_dict()), 201
// Express error handler
class APIError extends Error {
constructor(statusCode, code, message, details = []) {
super(message);
this.statusCode = statusCode;
this.code = code;
this.details = details;
}
}
function errorHandler(err, req, res, next) {
const status = err.statusCode || 500;
const response = {
error: {
code: err.code || 'INTERNAL_ERROR',
message: err.message || 'An unexpected error occurred',
details: err.details || [],
request_id: req.requestId
}
};
res.status(status).json(response);
}
app.use(errorHandler);
Common Mistakes
1. Inconsistent Error Structure
Some errors return {error: "msg"}, others {message: "err"}.
2. No Error Codes
Clients must string-match error messages instead of checking codes.
3. Exposing Stack Traces
Stack traces leak internal implementation details.
4. Generic Error Messages
"An error occurred" gives no information about what went wrong.
5. No Request ID
Clients can't reference specific failed requests in support tickets.
Practice Questions
- What fields should an error response include?
- Why use error codes instead of just messages?
- What is the HTTP status code for validation errors?
- Why include a request ID?
- How do you handle multiple validation errors?
Answers:
- code, message, details (array), request_id, documentation_url.
- Error codes are machine-readable; messages are for humans.
- 422 Unprocessable Entity (or 400 Bad Request).
- So support can trace the exact request that failed.
- Return all validation errors in the details array.
Challenge: Implement a consistent error response format across your API. Create an error handler that catches all exceptions and returns the standard format.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro