Browse documentation

Errors and recovery contracts

Give clients machine readable problems, safe recovery instructions and an error vocabulary that stays stable.

On this page
Before you start
  • HTTP response semantics
  • Validation rules
  • An operational correlation key

From a failed rule to a useful response

Translate internal failure into a stable public problem without exposing implementation details.

From a failed rule to a useful responseStep 1: Client to Request validator. Submit representation. Step 2: Request validator to Problem mapper. Identify failed rule. Step 3: Problem mapper to Operations log. Record diagnostic context. Step 4: Problem mapper to Client. Return problem details.ClientRequest validatorProblem mapperOperations logSubmit representation1Identify failed rule2Record diagnostic context3Return problem details4

Scroll across the diagram to see all four systems.

Inspect each exchange

Submit representation

Parse the request and establish the authenticated context.

Use a problem type as a stable contract

RFC 9457 defines application/problem+json for API problem details. The type identifies the kind of problem; title gives its human readable summary. The detail describes this occurrence, while instance can identify this particular failure. Clients should branch on a documented type or extension code, not on translated prose.

A problem body supplements HTTP status. It does not replace it. A proxy may change or remove a body, and generic clients still need the correct status to decide whether authentication, validation or retry is relevant.

Field validation responsejson
{
  "type": "https://api.example.test/problems/invalid-contact",
  "title": "Contact validation failed",
  "status": 422,
  "detail": "Correct the listed fields before submitting again.",
  "instance": "/requests/req_2409",
  "errors": [
    {
      "pointer": "/email",
      "code": "invalid_format",
      "message": "Provide an email address with a valid format."
    }
  ]
}

Separate a failed request from a failed dependency

Use 400 when the request cannot be interpreted, 401 when valid authentication is absent, and 403 when the authenticated action is denied. Use 409 for a conflict with current resource state and 412 for a failed request precondition. Validation of understood content can use 422.

For 429 or a temporary service failure, describe the retry policy separately from the business result. A timeout after a write is an unknown outcome, not evidence that no write occurred. The client must reconcile that uncertainty before creating a second business action.

ConditionClient actionAvoid
401Obtain valid credentials through the configured flow.Retrying the same expired token indefinitely.
403Review action scope or object permission.Automatically requesting broader permissions.
409 / 412Read current state and resolve the conflict.Blindly replaying a stale mutation.
422Correct the specific representation.Retrying the unchanged payload.
429 / 503Respect retry guidance and the operation deadline.Immediate synchronized retries from every worker.

Point to the field without leaking the record

For validation errors, expose a machine readable path such as a JSON Pointer plus a stable reason code. If several fields are invalid, return the useful set in one response. Limit list size to avoid turning error handling into an unbounded response.

Avoid revealing whether a protected email, account or tenant exists. Detailed database errors, stack traces, signing material and upstream response bodies belong in restricted logs. A public request reference lets support locate diagnostics without publishing them.

Keep failure rendering simpler than the failing system

A failure response should remain available when a downstream service is unavailable. Do not require the failed dependency to build the error description. Return the safest known status and preserve the trace context for later diagnosis.

Treat problem type changes like schema changes. New optional fields can be additive; changing the meaning of an existing type can break a client even when its JSON parser still succeeds.

Test the recovery instruction as well as the status

For each public problem, test the actual next action: reauthentication, payload correction, refresh, delayed retry or manual review. Verify that the described recovery can succeed and does not duplicate work.

Include non JSON intermediary responses, empty bodies and connection loss in client tests. A robust client must fall back to the transport status and correlation context when the preferred error document is absent.

Classify a request failure

Inspect how authentication, business validation and dependency availability map to distinct responses.

POST/api/v1/contacts

Contract inputs

Includes request values and the server validation context defined below.

Expected outcome

HTTP 201

Contact created

The request passes identity and representation checks before one record is created.

{
  "id": "contact_241",
  "email": "alex@example.test"
}

Decision path

  1. Authenticate
  2. Validate contact representation
  3. Persist the contact
  4. Return its resource location
Input schema 3 fields
FieldTypeMeaning
authenticatedRequiredbooleanWhether authentication succeeded.
email_validRequiredbooleanResult of the email representation check.
dependency_availableRequiredbooleanWhether the required write service is available.
Download JSON Schema

Standards and documentation

Explore the protocol specifications and platform guidance for this topic.

Bring the contract into your operating environment.

Discuss an implementation

Image preview