Skip to main content

Cloudsoft Zone Build, deploy and scale with practical guides to PHP, Node.js, React, DevOps and AI automation. Explore the guides

Cloudsoft Zone
DevelopmentArchitecture guide

Consistent API error responses with RFC 9457 Problem Details

Every HTTP API needs an error format, and most teams invent their own. RFC 9457 defines a standard one: application/problem+json. This guide explains its members, shows validation and business-rule examples, and covers design and security rules for adopting it.

Cloudsoft Zone

Updated 7 min read

Rows of servers in tall racks inside a data centre with cabling overhead
Photograph: Florian Hirzinger - www.fh-ap.com / CC BY-SA 3.0, via Wikimedia Commons
In this article

Ask three HTTP APIs for something they cannot do and you will often get three different error shapes: one returns {"error": "Bad request"}, another returns {"message": ..., "code": 1042}, and a third returns an HTML error page with a 200 status. Every client then needs custom parsing for each API, and every new endpoint is a chance for the format to drift.

RFC 9457, "Problem Details for HTTP APIs", is the IETF's answer. Published in July 2023 on the Standards Track, it defines a small JSON (and XML) object for carrying machine-readable error details in HTTP responses, so that APIs do not have to invent their own format. It obsoletes RFC 7807, which introduced the same idea in 2016.

This guide explains the format member by member, shows realistic examples for validation and business-rule errors, and lists the design decisions and security rules you need to settle before adopting it across an API. The examples are plain HTTP and JSON, so they apply to any server language or framework.

The shape of a problem details response

A problem details object is a JSON object served with the media type application/problem+json. Here is the RFC's own example, an online store refusing a purchase because the account lacks credit:

HTTP
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json
Content-Language: en

{
  "type": "https://example.com/probs/out-of-credit",
  "title": "You do not have enough credit.",
  "detail": "Your current balance is 30, but that costs 50.",
  "instance": "/account/12345/msgs/abc",
  "balance": 30,
  "accounts": ["/account/12345", "/account/67890"]
}

The first four members are defined by the RFC; balance and accounts are extension members defined by this particular problem type. Clients that know the type can use them; clients that do not must ignore them.

The standard members

MemberTypePurpose and rules from RFC 9457
typeURI referenceIdentifies the problem type and is the primary identifier consumers MUST use. Defaults to about:blank when absent. If it is an http(s) URL, dereferencing it SHOULD give human-readable documentation, but clients SHOULD NOT fetch it automatically.
statusNumberThe HTTP status code, advisory only. Servers MUST use the same code in the actual response.
titleStringShort human-readable summary of the problem type. SHOULD NOT change between occurrences, except for localisation.
detailStringExplanation specific to this occurrence, focused on helping the client fix the problem. Consumers SHOULD NOT parse it.
instanceURI referenceIdentifies this specific occurrence. May be dereferenceable, or an opaque identifier meaningful to the server.

type is the contract

The most important design decision is the set of type URIs. Clients branch on type, not on title or detail. Use absolute HTTPS URLs under a domain you control, such as https://api.example.com/problems/insufficient-stock, and publish a short documentation page at each one. The RFC warns that relative URIs "can cause confusion" and may not be handled correctly by all implementations.

about:blank for plain HTTP errors

When an error has no meaning beyond its status code, such as a generic 404, omit type or set it to about:blank. In that case the RFC says title SHOULD be the standard reason phrase for the status code, for example "Not Found" for 404.

HTTP
HTTP/1.1 404 Not Found
Content-Type: application/problem+json

{
  "type": "about:blank",
  "title": "Not Found",
  "status": 404,
  "detail": "No invoice exists with ID inv_20817."
}
Server room with rows of black equipment racks and a raised floor
API servers generate problem details centrally so every endpoint returns errors in one shape.

Validation errors with an errors extension

Validation failures often involve several fields at once. RFC 9457 shows a pattern for this: a problem type that defines an errors extension, an array where each entry has a detail and a pointer into the request body using JSON Pointer syntax (RFC 6901).

HTTP
POST /details HTTP/1.1
Host: account.example.com
Accept: application/json

{
  "age": 42.3,
  "profile": {
    "color": "yellow"
  }
}
HTTP
HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json
Content-Language: en

{
  "type": "https://example.net/validation-error",
  "title": "Your request is not valid.",
  "errors": [
    {
      "detail": "must be a positive integer",
      "pointer": "#/age"
    },
    {
      "detail": "must be 'green', 'red' or 'blue'",
      "pointer": "#/profile/color"
    }
  ]
}

The pointers let a client attach each message to the right form field without parsing text. For query-string or header errors, define your own member (for example parameter or header) in the problem type's documentation.

When a request has several problems of different types, the RFC recommends returning the most relevant or urgent one rather than inventing a generic batch format.

Designing your problem types

Treat problem types like any other part of your API contract. A workable process:

  1. List the errors clients must handle differently. "Out of stock", "payment declined" and "version conflict" lead to different user actions; a server bug does not. Only distinct handling needs a distinct type.
  2. Give each a stable URI and a fixed title. The title describes the type, so it stays the same across occurrences.
  3. Choose the status code first, then the type. For example, RFC 9110 defines 422 (Unprocessable Content) for requests whose syntax is correct but whose instructions cannot be processed. The status code still drives generic HTTP behaviour such as caching and retries; the type refines it.
  4. Define extension members per type. Name them carefully: the RFC notes that names must also be valid XML names if you support the XML format. Clients must ignore unknown members, so adding a member later is backward compatible.
  5. Document each type at its URI: when it occurs, its status code, its extension members and what the client should do.
  6. Check the IANA registry first. RFC 9457 created the "HTTP Problem Types" registry for common, reusable types. Vendor- and application-specific types cannot be registered, so most of your types will live under your own domain.

A small catalogue for an ordering API might look like this:

Type URI (suffix)StatusExtension membersClient action
/problems/validation-error422errors[] with detail and pointerShow messages next to fields
/problems/insufficient-stock409sku, availableOffer a lower quantity
/problems/stale-version409currentVersionReload and reapply the edit
about:blank404, 405, 500 and othersNoneGeneric handling by status

Security rules you must not skip

Error responses are a common source of information leaks. Section 5 of RFC 9457 asks generators to scrutinise what they include, warning about details that could compromise the system, access to it or users' privacy. In practice:

  • Never include stack traces, SQL, file paths or internal hostnames in detail or extensions. The RFC specifically discourages exposing stack dumps through the HTTP interface.
  • Do not reveal whether a resource exists to a caller who is not allowed to see it. Return the same problem for "not found" and "not permitted" where that matters.
  • Use instance or a request ID for correlation. Put an opaque identifier in the response and keep the full diagnostic data in your logs.
  • Keep status and the real status code identical. The RFC notes that the member duplicates the HTTP status and can disagree with it, for example when an intermediary changes the response; generic HTTP software always uses the real code.
  • Validate and encode on the client too. If a client shows detail in a web page, treat it as untrusted text and escape it.
Open server racks with networking equipment and neatly bundled cables
Keep diagnostic detail in server logs and send clients only an opaque instance or request identifier.

Content negotiation and adoption

Clients can signal support with Accept: application/json, application/problem+json. The RFC also defines application/problem+xml for XML APIs, and human-readable strings can be localised with Accept-Language, returning a matching Content-Language.

Problem details fit 4xx and 5xx responses most naturally, though the RFC allows them with any status. It also points out that they are not the only way to describe a problem: if the response is still a representation of a resource, a normal resource response may be the better fit.

To roll the format out across an existing API without breaking clients:

  • Produce every error from one central error handler, so no endpoint builds its own error body.
  • Write contract tests that assert the media type and the presence of type and title for each documented error.
  • Describe the problem object once in your OpenAPI document and reference it from every error response.
  • If old clients depend on legacy fields, include them temporarily as extension members, announce a removal date and remove them in the next major version.

Summary

RFC 9457 gives HTTP APIs a standard, extensible error format: type to identify the problem, title to summarise it, status to mirror the HTTP code, detail to explain this occurrence and instance to identify it, plus any extension members your types define. Adopt it by cataloguing the errors clients must handle differently, giving each a documented HTTPS type URI, centralising error generation and keeping internal details out of responses. Your clients get one parser for every error, and your API gains a contract that can grow without breaking them.

Frequently asked questions

  • Is RFC 7807 still valid?

    RFC 9457 obsoletes RFC 7807. The core members are the same, so RFC 7807 responses remain recognisable, but new work should follow RFC 9457, which also created the IANA registry of common problem types.

  • Which members are required?

    None is strictly required. If type is absent it defaults to about:blank. In practice, always send type and title, and include status and detail when they help clients.

  • Can clients parse the detail string?

    They should not. The RFC says consumers SHOULD NOT parse detail; any data a client needs belongs in an extension member defined by the problem type.

  • What content type should the response use?

    Use application/problem+json for JSON, or application/problem+xml for the XML format defined in the RFC's appendix.

Advertise on CloudSoftZone

Your next customer could start right here.

Introduce your tool, product or business to readers exploring technology.

Advertise with us

Explore placements and request a private quote

Sources

  1. RFC 9457: Problem Details for HTTP APIs — IETF / RFC Editor
  2. RFC 9110: HTTP Semantics (422 Unprocessable Content) — IETF / RFC Editor
  3. RFC 6901: JavaScript Object Notation (JSON) Pointer — IETF / RFC Editor
  4. HTTP Problem Types registry — IANA, 2026-06-26

Written with substantial AI assistance. Facts checked against cited sources. Editorial policy.

Comments

No comments yet. Be the first to join the conversation.

Leave a comment

Every comment is read by a moderator before it appears. Your email address is never published; it is used only to contact you about this comment.

Never published. Used only to contact you about this comment.

Loading the security check…

Comments are moderated before publication.

  • Rows of server racks with cabling in a data centre aisle

    Resource guideWordPress

    WordPress security hardening checklist for 2026 (WordPress 7.1)

    A practical WordPress 7.1 hardening checklist based on the official handbook: updates, two-step logins, wp-config.php constants, file permissions, database privileges, firewalls, WP-CLI checksum checks and tested backups.

    By Cloudsoft Zone