DEV Community

Cover image for What Is RFC 9457 and How Should APIs Return Errors?
Wanda
Wanda

Posted on • Originally published at apidog.com

What Is RFC 9457 and How Should APIs Return Errors?

TL;DR

RFC 9457 (Problem Details for HTTP APIs) is the standard for API error responses. It establishes a consistent structure—type, title, status, detail, and instance—to replace custom error formats. Modern PetstoreAPI implements RFC 9457 for all error responses with correct content negotiation and validation detail support.

Try Apidog today

Introduction

When your API returns an error, what does the response look like? If you're like most APIs, you likely have a custom format:

{"error": "Invalid email"}
{"message": "Not found", "code": 404}
{"success": false, "errors": ["Email required"]}
Enter fullscreen mode Exit fullscreen mode

Every API invents its own error structure, making client-side error handling inconsistent and error-prone. There’s no standardized way to parse, display, or log errors.

RFC 9457 fixes this by defining a standard, machine-readable error response format that clients can rely on.

The old Swagger Petstore used inconsistent error formats. Modern PetstoreAPI now implements RFC 9457 throughout, delivering structured and predictable error details.

💡 Tip: If you're building or testing REST APIs, Apidog lets you validate error responses, test RFC 9457 compliance, and ensure your API returns correct error structures. Define expected error formats, run automated tests, and catch issues early.

In this guide, you'll learn what RFC 9457 is, how to implement it correctly, and how Modern PetstoreAPI uses it for all error responses.

The API Error Problem

Before RFC 9457, error formats varied widely.

Common Error Format Variations

Format 1: Simple message

{"error": "User not found"}
Enter fullscreen mode Exit fullscreen mode

Format 2: Code and message

{"code": "USER_NOT_FOUND", "message": "User not found"}
Enter fullscreen mode Exit fullscreen mode

Format 3: Nested structure

{
  "success": false,
  "error": {
    "type": "NotFound",
    "message": "User not found"
  }
}
Enter fullscreen mode Exit fullscreen mode

Format 4: Array of errors

{
  "errors": [
    {"field": "email", "message": "Invalid email"}
  ]
}
Enter fullscreen mode Exit fullscreen mode

Problems with Custom Formats

  1. No consistency: Clients must custom-parse each API's errors.
  2. Missing information: Some formats lack error codes or details.
  3. No machine-readable structure: Hard to handle errors programmatically.
  4. Poor internationalization: Messages are often hardcoded in English.
  5. No standard for validation errors: Field-level errors are handled inconsistently.

What Is RFC 9457?

RFC 9457 (published July 2023) is the IETF standard for "Problem Details for HTTP APIs." It prescribes a standard error response structure for APIs.

Key Features

  • Standard media type: application/problem+json (or application/problem+xml)
  • Consistent structure: All errors share the same fields
  • Machine-readable: Enables automated error handling
  • Extensible: Add custom fields as needed
  • HTTP-aware: Integrates with HTTP status codes

RFC 9457 vs Custom Errors

Custom error:

{"error": "Email is required"}
Enter fullscreen mode Exit fullscreen mode

RFC 9457 error:

{
  "type": "https://petstoreapi.com/errors/validation-error",
  "title": "Validation Error",
  "status": 400,
  "detail": "The request contains invalid data",
  "instance": "/pets",
  "errors": [
    {
      "field": "email",
      "message": "Email is required"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

The RFC 9457 format provides:

  • Type URL for documentation
  • Human-readable title
  • HTTP status code
  • Detailed explanation
  • Path of the error occurrence
  • Field-level validation details

RFC 9457 Structure Explained

RFC 9457 defines five standard fields, plus optional custom extensions.

Standard Fields

1. type (string, required):

A URI identifying the error type. Should point to documentation.

"type": "https://petstoreapi.com/errors/validation-error"
Enter fullscreen mode Exit fullscreen mode

If omitted, defaults to about:blank.

2. title (string, required):

Short, human-readable summary. Should not vary between occurrences.

"title": "Validation Error"
Enter fullscreen mode Exit fullscreen mode

3. status (number, required):

The HTTP status code.

"status": 400
Enter fullscreen mode Exit fullscreen mode

4. detail (string, optional):

Human-readable explanation for this specific error.

"detail": "The email field must be a valid email address"
Enter fullscreen mode Exit fullscreen mode

5. instance (string, optional):

A URI identifying the specific occurrence, usually the request path.

"instance": "/pets/019b4132-70aa-764f-b315-e2803d882a24"
Enter fullscreen mode Exit fullscreen mode

Custom Extensions

Add custom fields for more context as needed:

{
  "type": "https://petstoreapi.com/errors/rate-limit-exceeded",
  "title": "Rate Limit Exceeded",
  "status": 429,
  "detail": "You have exceeded the rate limit of 100 requests per minute",
  "instance": "/pets",
  "retryAfter": 42,
  "limit": 100,
  "remaining": 0,
  "resetAt": "2026-03-13T10:30:00Z"
}
Enter fullscreen mode Exit fullscreen mode

How Modern PetstoreAPI Implements RFC 9457

Modern PetstoreAPI returns RFC 9457-compliant error responses for all API errors.

Example 1: Resource Not Found

GET /pets/invalid-id
404 Not Found
Content-Type: application/problem+json

{
  "type": "https://docs.petstoreapi.com/errors/not-found",
  "title": "Resource Not Found",
  "status": 404,
  "detail": "The requested pet does not exist",
  "instance": "/pets/invalid-id"
}
Enter fullscreen mode Exit fullscreen mode

Example 2: Authentication Error

GET /pets
401 Unauthorized
Content-Type: application/problem+json

{
  "type": "https://docs.petstoreapi.com/errors/unauthorized",
  "title": "Authentication Required",
  "status": 401,
  "detail": "Valid authentication credentials are required to access this resource",
  "instance": "/pets"
}
Enter fullscreen mode Exit fullscreen mode

Example 3: Rate Limit Exceeded

GET /pets
429 Too Many Requests
Content-Type: application/problem+json
Retry-After: 60

{
  "type": "https://docs.petstoreapi.com/errors/rate-limit-exceeded",
  "title": "Rate Limit Exceeded",
  "status": 429,
  "detail": "You have exceeded the rate limit of 100 requests per minute",
  "instance": "/pets",
  "limit": 100,
  "remaining": 0,
  "resetAt": "2026-03-13T10:31:00Z"
}
Enter fullscreen mode Exit fullscreen mode

See the Modern PetstoreAPI error handling documentation for more examples.

Validation Errors with RFC 9457

Field-level validation errors are supported via custom extensions.

Modern PetstoreAPI Validation Format

POST /pets
400 Bad Request
Content-Type: application/problem+json

{
  "type": "https://docs.petstoreapi.com/errors/validation-error",
  "title": "Validation Error",
  "status": 400,
  "detail": "The request contains 2 validation errors",
  "instance": "/pets",
  "errors": [
    {
      "field": "name",
      "message": "Name is required",
      "code": "REQUIRED_FIELD"
    },
    {
      "field": "species",
      "message": "Species must be one of: DOG, CAT, BIRD, FISH, REPTILE, OTHER",
      "code": "INVALID_ENUM_VALUE",
      "rejectedValue": "DRAGON"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Key Points

  • errors array: Field-level validation details
  • field: Path to the invalid field
  • message: Human-readable message
  • code: Machine-readable error code
  • rejectedValue: The invalid value (optional)

This structure allows clients to:

  • Display field-level messages in forms
  • Highlight invalid user input
  • Show specific error messages
  • Programmatically handle validation errors

Testing Error Responses with Apidog

Apidog makes it easy to test RFC 9457 compliance.

Test Case: Validation Error

// Apidog test script
pm.test("Returns RFC 9457 error format", () => {
  const response = pm.response.json();

  // Required fields
  pm.expect(response).to.have.property("type");
  pm.expect(response).to.have.property("title");
  pm.expect(response).to.have.property("status");

  // Status matches HTTP status
  pm.expect(response.status).to.equal(pm.response.code);

  // Content-Type check
  pm.expect(pm.response.headers.get("Content-Type"))
    .to.include("application/problem+json");
});

pm.test("Validation errors include field details", () => {
  const response = pm.response.json();

  pm.expect(response).to.have.property("errors");
  pm.expect(response.errors).to.be.an("array");

  response.errors.forEach(error => {
    pm.expect(error).to.have.property("field");
    pm.expect(error).to.have.property("message");
  });
});
Enter fullscreen mode Exit fullscreen mode

Test Case: Error Type URLs

pm.test("Error type URL is accessible", async () => {
  const response = pm.response.json();
  const typeUrl = response.type;

  // Verify type URL returns documentation
  const docResponse = await pm.sendRequest(typeUrl);
  pm.expect(docResponse.code).to.equal(200);
});
Enter fullscreen mode Exit fullscreen mode

Migration from Custom Error Formats

To migrate your API to RFC 9457:

Step 1: Add Content-Type Header

Return RFC 9457 errors as:

Content-Type: application/problem+json
Enter fullscreen mode Exit fullscreen mode

Step 2: Map Existing Fields

Convert your custom error fields to RFC 9457 fields.

Before:

{
  "error": "USER_NOT_FOUND",
  "message": "User not found"
}
Enter fullscreen mode Exit fullscreen mode

After:

{
  "type": "https://api.example.com/errors/user-not-found",
  "title": "User Not Found",
  "status": 404,
  "detail": "User not found"
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Support Both Formats (Transition Period)

Use content negotiation to support both formats:

Accept: application/json           → Returns custom format
Accept: application/problem+json   → Returns RFC 9457 format
Enter fullscreen mode Exit fullscreen mode

Step 4: Deprecate Custom Format

Once clients are migrated, deprecate your old format and use RFC 9457 by default.

Conclusion

RFC 9457 standardizes API error responses, replacing ad-hoc formats with a predictable, machine-readable structure. It improves error handling, debugging, and client integration.

Modern PetstoreAPI demonstrates full RFC 9457 adoption, including correct validation error structures, type URLs, and status codes.

Use Apidog to automate RFC 9457 compliance checks and error response validation in your API projects.

FAQ

Is RFC 9457 required for REST APIs?

No, but it's the recommended standard. Using RFC 9457 makes your API more consistent and easier to integrate.

Can I use RFC 9457 with XML?

Yes—RFC 9457 supports both JSON (application/problem+json) and XML (application/problem+xml) formats.

Should I always include all five standard fields?

type, title, and status are required. detail and instance are optional but recommended for context.

Can I add custom fields to RFC 9457 responses?

Yes. RFC 9457 is extensible—add custom fields like errors, retryAfter, or traceId as needed.

How do I handle validation errors with RFC 9457?

Add a custom errors array with field-level error details. See Modern PetstoreAPI for a reference implementation.

What should the error type URL point to?

It should point to human-readable documentation explaining the error type, causes, and possible fixes.

Do I need to change HTTP status codes when using RFC 9457?

No. Use standard HTTP status codes; the status field in the body should match the HTTP status code.

How do I test RFC 9457 compliance?

Use Apidog to validate your error response structure, required fields, and content types.

Top comments (0)