Skip to content

Restful Error Responses

DodaTech 2 min read

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

  1. What fields should an error response include?
  2. Why use error codes instead of just messages?
  3. What is the HTTP status code for validation errors?
  4. Why include a request ID?
  5. How do you handle multiple validation errors?

Answers:

  1. code, message, details (array), request_id, documentation_url.
  2. Error codes are machine-readable; messages are for humans.
  3. 422 Unprocessable Entity (or 400 Bad Request).
  4. So support can trace the exact request that failed.
  5. 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

What error code should I use for unexpected errors?

: INTERNAL_ERROR or SERVER_ERROR for 500 responses.

Should I include debug information in development?

: Yes, but strip it in production.

How detailed should error messages be?

: Detailed enough for a developer to fix the issue, but not exposing internals.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro