API errors: offer clear actions without exposing secrets

At a glance

An error response should help a client decide whether to correct input, renew authentication, request permission or wait. Public messages and internal diagnosis need different levels of detail.

Empty secure server and network corridor Illustration · fictional scene
In this article

Separate status, type and occurrence

RFC 9457 defines the application/problem+json format. Use a stable problem type and an understandable detail for the occurrence; clients should not parse translated prose to choose an action. If the status member is present, keep it consistent with the actual HTTP status.

StatusHTTP meaningHandling to consider
400Bad requestCorrect the request before another attempt.
401Valid authentication credentials absentCheck credentials and the documented mechanism.
403Request understood but refusedReview permissions; repeating cannot grant them.
503Service temporarily unavailableWait and retry within bounds if the operation permits.

Make failure paths predictable

  • Document codes, formats and expected handling. Also test empty responses, non-JSON gateway content, interrupted connections and timeouts.
  • Validate input and permissions on the server. Handle expected failures without concealing unknown faults; do not use success responses to hide a business failure.
  • Return a correlation identifier support can use. Keep stack traces, internal queries, passwords and tokens out of public responses.

Retry only when it makes sense

The 5xx class does not authorize an unlimited retry loop. Combine the contract, operation state, idempotency and overall deadline. To report a defect, provide a minimal, redacted reproduction; after a fix, retest the original case and nearby access-denial cases.

Primary references

Further reading

API errors should guide action without leakage

HTTP status supplies an initial category, but a client may need a stable type and useful detail. RFC 9457 describes a common problem structure; it does not justify exposing internal traces or sensitive data.

  • Separate permanent refusal, correctable input and temporary failure.
  • Document type, status and possible client action for each important error.
  • Test that responses contain no secrets or unnecessary full payloads.

Primary reference: IETF RFC 9457 — Problem Details for HTTP APIs. Related method: read the practical guide.

API retries: count the end-to-end budget

An error policy needs repeatable cases, total call count and a deadline. The calculation below exposes a configuration that already exceeds its budget before business effects are tested.

Fictional teaching case — figures describe neither CIE nor a client.

This fictional scenario has four total attempts, each limited to 250 ms, with deterministic waits of 100, 200 and 400 ms. The modelled budget is 1,700 ms: 1,000 ms of calls and 700 ms waiting. It exceeds a 1,500 ms deadline before other journey costs are counted.

Total attempts
4One initial attempt and three retries
Accumulated waits
700 ms100 + 200 + 400
Modelled budget
1,700 ms4 × 250 + 700
Break down the fictional sequence
StepMaximum call timeWait before next call
Attempt 1250 ms100 ms
Attempt 2250 ms200 ms
Attempt 3250 ms400 ms
Attempt 4250 msNone
Total1,000 ms700 ms
Durations in the same model (ms)
  • Calls1,000 ms
  • Waits700 ms
  • Entered deadline1,500 ms

Checks for interpreting the case

  1. Propagate a global deadline and bound each call by the remaining time. Avoid stacking independent retry policies across layers.
  2. Verify the operation can be repeated without duplicate effects. A timeout does not establish that the remote server stopped processing.
  3. This model excludes jitter, caps, Retry-After, DNS resolution, connection, queues and local validation. Measure these costs before configuring a service.
When retries make an outage worse

A duration budget is only one condition. An operation may be fast enough yet unsafe to repeat or may amplify load on an unavailable provider.

When retries make an outage worse
Signal to examineConcrete checkEffect on the decision
Non-idempotent actionCheck the key, its scope and server-side result retention.Reconcile state before repeating a creation or payment.
Retries at multiple layersCount attempts from the browser, gateway and service.Assign retry ownership and an end-to-end budget.
Sustained outageCheck deadline, cancellation and the journey without the provider.Provide explicit degradation and controlled recovery.

From a number to a verification

Exercise the complete failure scenario

Test to reproduce
Test unavailability, slow responses and response loss after processing. Check idempotency before retrying a write and count retries in intermediate layers too.
Stop signal
Retrying a non-idempotent operation without knowing whether the first attempt took effect.

Change an assumption

Reduce retries without duplicating the business action

The preceding example allows four attempts and reaches 1,700 ms. Here is what one fewer attempt changes, keeping modelled budget separate from observed duration.

  1. Three attempts

    3 × 250 ms = up to 750 ms of calls in the model.

  2. Two waits

    100 + 200 ms = 300 ms; modelled total: 1,050 ms.

  3. Deadline

    That leaves 450 ms out of 1,500 ms for other costs, without guaranteeing they fit.

Reading exercise: the variations describe fictional situations.

What if the first attempt already created the order?
New evidence
The server processed the action, but its response was lost.
What changes
Another attempt may repeat the business effect. Verify idempotency or retrieve operation state before resending the action. Timing arithmetic cannot solve this problem.
What if three layers each allow three attempts?
New evidence
In a simplified maximum case, three attempts at each of three levels can produce 27 downstream calls.
What changes
Identify the layer responsible for retries and the overall budget. The product 3 × 3 × 3 describes this scenario, not a fixed production volume.
Why count attempts rather than retries?

One initial attempt plus three retries makes four calls. Distinct names avoid an off-by-one error in configuration and calculation.

Try a retry budget

n × timeout + wait × (2^(n−1) − 1). Doubling waits, without jitter or caps.

Related method: read the practical guide.

API errors: types, statuses and evidence

Handle an error without parsing its sentence

An API client may receive a translated title, missing member or unfamiliar extension. Preserve decisions based on the documented type and HTTP status, then connect a safe action to the context.

  • Compare received status and JSON status without silently replacing either.
  • Test absent type, string status instead of a number, and an unknown extension.
  • Separate person-facing text, business code and occurrence reference.

Explore problem types and eight fictional responses →

IETF · M. Nottingham, E. Wilde, S. Dalal · RFC 9457 · July 2023 · obsoletes RFC 7807 · §3.1, §3.2, §4.2, §5