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.
| Status | HTTP meaning | Handling to consider |
|---|---|---|
| 400 | Bad request | Correct the request before another attempt. |
| 401 | Valid authentication credentials absent | Check credentials and the documented mechanism. |
| 403 | Request understood but refused | Review permissions; repeating cannot grant them. |
| 503 | Service temporarily unavailable | Wait 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
| Step | Maximum call time | Wait before next call |
|---|---|---|
| Attempt 1 | 250 ms | 100 ms |
| Attempt 2 | 250 ms | 200 ms |
| Attempt 3 | 250 ms | 400 ms |
| Attempt 4 | 250 ms | None |
| Total | 1,000 ms | 700 ms |
- Calls1,000 ms
- Waits700 ms
- Entered deadline1,500 ms
Checks for interpreting the case
- Propagate a global deadline and bound each call by the remaining time. Avoid stacking independent retry policies across layers.
- Verify the operation can be repeated without duplicate effects. A timeout does not establish that the remote server stopped processing.
- 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.
| Signal to examine | Concrete check | Effect on the decision |
|---|---|---|
| Non-idempotent action | Check the key, its scope and server-side result retention. | Reconcile state before repeating a creation or payment. |
| Retries at multiple layers | Count attempts from the browser, gateway and service. | Assign retry ownership and an end-to-end budget. |
| Sustained outage | Check 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.
- Three attempts
3 × 250 ms = up to 750 ms of calls in the model.
- Two waits
100 + 200 ms = 300 ms; modelled total: 1,050 ms.
- 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
