TL;DR
RFC 9457, “Problem Details for HTTP APIs,” defines a standard format for API errors. It replaces custom error payloads with a consistent structure based on type, title, status, detail, and instance. Modern PetstoreAPI uses RFC 9457 for its error responses, including content negotiation and field-level validation details.
Introduction
When an API returns an error, the response often uses a custom format:
{"error": "Invalid email"}
{"message": "Not found", "code": 404}
{"success": false, "errors": ["Email required"]}
Every custom format increases integration work. Clients need different parsing logic for each API, and there is no consistent way to display errors, log diagnostic details, or handle validation failures.
RFC 9457 solves this by defining a standard error format that clients can parse consistently. Instead of inventing a new structure, return a problem details object with a standard media type:
Content-Type: application/problem+json
The old Swagger Petstore used custom error formats with no consistency. Modern PetstoreAPI implements RFC 9457 across its error responses, providing structured, machine-readable error details.
In this guide, you’ll learn how RFC 9457 works, how to implement it, and how to test your API for compliance.
The API Error Problem
Before RFC 9457, APIs commonly returned errors in several incompatible formats.
Common Error Format Variations
Format 1: Simple message
{
"error": "User not found"
}
Format 2: Code and message
{
"code": "USER_NOT_FOUND",
"message": "User not found"
}
Format 3: Nested structure
{
"success": false,
"error": {
"type": "NotFound",
"message": "User not found"
}
}
Format 4: Array of errors
{
"errors": [
{
"field": "email",
"message": "Invalid email"
}
]
}
Problems with Custom Formats
Custom error formats create several problems:
- No consistency: Clients need custom parsing logic for each API.
- Missing information: Some formats omit error codes, details, or both.
- Limited machine readability: Clients cannot reliably process errors programmatically.
- Poor internationalization: Hardcoded messages are difficult to translate.
- No standard validation structure: APIs represent field-level errors differently.
What Is RFC 9457?
RFC 9457, published in July 2023, defines “Problem Details for HTTP APIs.” It is an IETF standard for structuring HTTP error responses.
Key Features
-
Standard media types:
application/problem+jsonandapplication/problem+xml - Consistent structure: Errors use the same core fields
- Machine-readable data: Clients can process errors programmatically
- Extensibility: APIs can add custom fields without breaking the standard structure
- HTTP integration: Problem details work with standard HTTP status codes
RFC 9457 vs. Custom Errors
A custom error might look like this:
{
"error": "Email is required"
}
An RFC 9457 response can provide more context:
{
"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"
}
]
}
This response includes:
- A type URL for error documentation
- A stable, human-readable title
- The HTTP status code
- A description of the specific failure
- The request path associated with the error
- Field-level validation details
RFC 9457 Structure Explained
RFC 9457 defines five standard fields and allows custom extensions.
Standard Fields
1. type
type is a URI reference that identifies the error type. Ideally, it points to human-readable documentation.
{
"type": "https://petstoreapi.com/errors/validation-error"
}
If omitted, type defaults to about:blank.
2. title
title is a short, human-readable summary of the error type. It should remain stable between occurrences of the same error type.
{
"title": "Validation Error"
}
3. status
status contains the HTTP status code associated with the problem.
{
"status": 400
}
The value should match the status code in the HTTP response.
4. detail
detail is a human-readable explanation specific to the current occurrence.
{
"detail": "The email field must be a valid email address"
}
5. instance
instance identifies the specific occurrence of the problem. It is often set to the request path.
{
"instance": "/pets/019b4132-70aa-764f-b315-e2803d882a24"
}
Custom Extensions
You can add fields for application-specific context while keeping the standard fields intact:
{
"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"
}
Common extension fields include:
-
errorsfor field-level validation failures -
retryAfterfor retry timing -
traceIdfor correlating logs and requests - Rate-limit metadata such as
limit,remaining, andresetAt
Implementing RFC 9457 in an API
A typical implementation should:
- Define a consistent problem details schema.
- Set
Content-Type: application/problem+jsonfor error responses. - Map each error category to a stable
typeURI. - Ensure the response
statusmatches the HTTP status code. - Add extension fields for validation or domain-specific details.
- Test both the payload and response headers.
A generic error response might look like this:
HTTP/1.1 404 Not Found
Content-Type: application/problem+json
{
"type": "https://api.example.com/errors/resource-not-found",
"title": "Resource Not Found",
"status": 404,
"detail": "The requested resource does not exist",
"instance": "/resources/invalid-id"
}
How Modern PetstoreAPI Implements RFC 9457
Modern PetstoreAPI uses RFC 9457 for its error responses.
Example 1: Resource Not Found
GET /pets/invalid-id
HTTP/1.1 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"
}
Example 2: Authentication Error
GET /pets
HTTP/1.1 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"
}
Example 3: Rate Limit Exceeded
GET /pets
HTTP/1.1 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"
}
See the Modern PetstoreAPI error handling documentation for all error types.
Handling Validation Errors with RFC 9457
Validation errors usually need more than a single message. Clients often need to know:
- Which field failed
- Why validation failed
- Which machine-readable rule was violated
- Which value was rejected
RFC 9457 allows this information through custom extension fields.
Modern PetstoreAPI Validation Format
POST /pets
HTTP/1.1 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"
}
]
}
Validation Field Conventions
The errors array contains field-level validation details:
-
field: The JSON path to the invalid field -
message: A human-readable explanation -
code: A machine-readable validation code -
rejectedValue: The value that failed validation, when appropriate
Clients can use this structure to:
- Display field-level errors in forms
- Highlight invalid fields
- Show specific error messages
- Handle validation failures programmatically
Testing Error Responses with Apidog
Apidog can help validate RFC 9457 response structures, headers, and status codes.
Test Case: Validate the Problem Details Structure
pm.test("Returns RFC 9457 error format", () => {
const response = pm.response.json();
pm.expect(response).to.have.property("type");
pm.expect(response).to.have.property("title");
pm.expect(response).to.have.property("status");
pm.expect(response.status).to.equal(pm.response.code);
pm.expect(pm.response.headers.get("Content-Type"))
.to.include("application/problem+json");
});
Test Case: Validate Field-Level Errors
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");
});
});
Test Case: Verify Error Type URLs
If your type values point to documentation endpoints, test that those URLs are accessible:
pm.test("Error type URL is accessible", async () => {
const response = pm.response.json();
const typeUrl = response.type;
const docResponse = await pm.sendRequest(typeUrl);
pm.expect(docResponse.code).to.equal(200);
});
When testing, check all of the following:
- The response uses
application/problem+json - The HTTP status and
statusfield match - Required problem details fields are present
- Validation responses include field-level information
- Error type URLs resolve to documentation when applicable
Migrating from Custom Error Formats
If your API already returns custom errors, migrate incrementally.
Step 1: Add the Problem Details Content Type
Return the RFC 9457 media type for problem responses:
Content-Type: application/problem+json
Step 2: Map Existing Fields
For example, convert this custom response:
{
"error": "USER_NOT_FOUND",
"message": "User not found"
}
Into an RFC 9457 response:
{
"type": "https://api.example.com/errors/user-not-found",
"title": "User Not Found",
"status": 404,
"detail": "User not found"
}
A practical field mapping looks like this:
| Custom field | RFC 9457 field |
|---|---|
error |
type or a custom code extension |
message |
detail |
| HTTP response code | status |
| Request identifier or path | instance |
Step 3: Support Both Formats During the Transition
Use content negotiation to support existing clients while introducing RFC 9457:
Accept: application/json
Return the legacy format for clients that still require it.
Accept: application/problem+json
Return the RFC 9457 format for migrated clients.
Document the transition clearly and test both representations.
Step 4: Deprecate the Custom Format
After clients have migrated, deprecate the legacy format and return RFC 9457 by default.
Conclusion
RFC 9457 provides a consistent, machine-readable format for HTTP API errors. It standardizes common fields such as type, title, status, detail, and instance while allowing extensions for validation and domain-specific data.
Modern PetstoreAPI demonstrates how to apply the standard across resource, authentication, rate-limit, and validation errors. A consistent response format makes it easier for clients to parse errors, display useful messages, and diagnose failures.
Use Apidog to test RFC 9457 compliance, validate error structures, verify content types, and confirm that response status codes match the status field.
FAQ
Is RFC 9457 required for REST APIs?
No. RFC 9457 is a recommended standard rather than a requirement. Using it makes APIs more consistent and easier for clients to integrate.
Can I use RFC 9457 with XML?
Yes. RFC 9457 defines both JSON and XML representations:
application/problem+jsonapplication/problem+xml
Should I always include all five standard fields?
type, title, and status are required in the structure described here. detail and instance are optional but useful for providing more context.
Can I add custom fields to RFC 9457 responses?
Yes. RFC 9457 is extensible. You can add fields such as errors, retryAfter, or traceId without changing the standard fields.
How do I handle validation errors with RFC 9457?
Add a custom errors array containing field-level details. Each item can include the field path, human-readable message, machine-readable code, and rejected value.
What should the error type URL point to?
It should point to human-readable documentation that explains the error type, its possible causes, and how to resolve it.
Do I need to change HTTP status codes when using RFC 9457?
No. RFC 9457 works with standard HTTP status codes. The response’s status field should match the HTTP status code.
How do I test RFC 9457 compliance?
Validate the response structure, required fields, content type, status-code consistency, and any custom validation fields. Apidog can be used to automate these checks.
Top comments (0)