Skip to main content

Error Response

What Are Meaningful Error Responses

A meaningful error response is a structured, consistent, and client-friendly way for a REST API to tell consumers:

  • What went wrong
  • Why it went wrong
  • How to fix it (when appropriate)

Good error responses combine:

  1. Correct HTTP status codes
  2. Clear error identifiers (error codes)
  3. Human-readable messages
  4. Optional error details

Why Meaningful Error Responses Matter

  1. Better Developer Experience (DX): Clients can quickly debug and fix issues
  2. Fewer Support Requests: Clear errors reduce confusion
  3. Consistent Client Behavior: Applications can programmatically handle errors
  4. Security: Avoids leaking internal system details
  5. Scalability: Enables error tracking, logging, and monitoring

Components of a Meaningful Error Response

A well-designed error response typically includes:

{
"errorCode": "INVALID_INPUT",
"message": "Request validation failed",
"details": []
}

Component Breakdown

ComponentPurpose
HTTP Status CodeHigh-level error category
errorCodeMachine-readable identifier
messageHuman-readable explanation
detailsField-level or contextual info

HTTP Status Codes

HTTP status codes communicate the category of the error.

Commonly Used Status Codes

StatusMeaningWhen to Use
400Bad RequestInvalid syntax or malformed input
401UnauthorizedMissing or invalid authentication
403ForbiddenAuthenticated but not allowed
404Not FoundResource does not exist
409ConflictResource state conflict
415Unsupported Media TypeWrong Content-Type
422Unprocessable EntitySemantic validation failure
500Internal Server ErrorUnexpected server failure

Error Codes (Machine-Readable)

Error codes are stable, application-specific identifiers that allow clients to:

  • Handle errors programmatically
  • Avoid parsing human-readable text
  • Support localization (i18n)

Example Error Codes

INVALID_INPUT
MISSING_REQUIRED_FIELD
AUTH_TOKEN_EXPIRED
RESOURCE_NOT_FOUND
PERMISSION_DENIED
RATE_LIMIT_EXCEEDED

Best Practices for Error Codes

  • Use UPPER_SNAKE_CASE
  • Keep them stable over time
  • Avoid exposing internal exceptions
  • Document them clearly

Error Messages (Human-Readable)

Characteristics of Good Error Messages

  • Clear and concise
  • Actionable when possible
  • Non-technical
  • Secure (no stack traces or SQL errors)
  • Bad message: "message": "NullPointerException at UserService.java:42"
  • Good message: "message": "Username is required"

Field-Level Validation Errors

Example: Invalid Request Body

Request

POST /users
Content-Type: application/json
{
"username": "",
"email": "invalid-email",
"age": 15
}

Response

HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{
"errorCode": "VALIDATION_ERROR",
"message": "One or more fields are invalid",
"details": [
{
"field": "username",
"issue": "Must not be empty"
},
{
"field": "email",
"issue": "Invalid email format"
},
{
"field": "age",
"issue": "Must be at least 18"
}
]
}

Explanation

  • 422 → request syntax is valid, but semantic rules failed
  • VALIDATION_ERROR → consistent error handling
  • details helps client highlight specific fields

Authentication Error Example

Missing Authorization Header

Request

GET /orders

Response

HTTP/1.1 401 Unauthorized
{
"errorCode": "AUTH_REQUIRED",
"message": "Authentication token is missing or invalid"
}

Explanation

  • 401 → client must authenticate
  • Message clearly indicates what’s missing
  • No internal auth logic exposed

Authorization Error Example

Insufficient Permissions

HTTP/1.1 403 Forbidden
{
"errorCode": "ACCESS_DENIED",
"message": "You do not have permission to access this resource"
}

Explanation

  • 403 → identity is known, but access is denied
  • Client should not retry with same credentials

Resource Not Found Example

Request

GET /users/9999

Response

HTTP/1.1 404 Not Found
{
"errorCode": "RESOURCE_NOT_FOUND",
"message": "User with ID 9999 was not found"
}

Explanation

  • Avoids leaking whether IDs are sequential or valid
  • Clear, domain-specific messaging

Conflict Error Example

Duplicate Resource Creation

POST /users
{
"email": "existing@example.com"
}

Response

HTTP/1.1 409 Conflict
{
"errorCode": "DUPLICATE_RESOURCE",
"message": "A user with this email already exists"
}

Explanation

  • 409 → state conflict
  • Message explains how to resolve (use another email)

Internal Server Error Example

Unexpected Failure

HTTP/1.1 500 Internal Server Error
{
"errorCode": "INTERNAL_ERROR",
"message": "An unexpected error occurred. Please try again later."
}

Explanation

  • Never expose stack traces
  • Detailed error logged server-side
  • Generic message protects security

Consistent Error Response Format

Standard Template

{
"errorCode": "STRING",
"message": "STRING",
"details": []
}

Optional Fields

{
"timestamp": "2026-01-09T10:15:30Z",
"path": "/users",
"requestId": "abc-123"
}