Errors
Distinguish application, OAuth, and infrastructure errors before retrying.
The format depends on what rejected the request. Errors produced by the
application flow use Problem Details with a code; Auth, a limiter, or a
gateway may return another structure.
Application errors
A domain or application error uses Problem Details:
{
"title": "Not Found",
"detail": "Product 7204558912004325377 does not exist.",
"status": 404,
"code": "Catalog.ProductNotFound"
}| Field | Use |
|---|---|
title | Human-readable error category. |
detail | Diagnostic explanation; it may change. |
status | Associated HTTP status. |
code | Application identifier for handling the case when present. |
Use code to distinguish known cases and keep status as a fallback. Do not
make decisions from the text in detail.
Validation
Validation errors may add an errors object with one or more messages per
field:
{
"title": "One or more validation errors occurred.",
"status": 400,
"code": "Common.Validation",
"errors": {
"limit": ["The limit must be between 1 and 200."]
}
}Show these messages so the input can be fixed. Do not assume all endpoints accept the same range or use the same key.
OAuth errors
POST /connect/token follows the OAuth error format. A failure may look like
this:
{
"error": "invalid_client",
"error_description": "The client credentials are invalid."
}Handle error and the HTTP status. Do not expect title, status, or code
in this response.
Infrastructure errors
A gateway, request-rate limiter, or concurrency limiter may respond before the request reaches the application. Keep the status, headers, and any request identifier.
Do not deserialize every error response into one mandatory model. Check the
Content-Type and allow for an empty or different body.
What to do by status
| Status | Common meaning | First action |
|---|---|---|
400 | Invalid body, parameter, or transition. | Fix the request; do not repeat it unchanged. |
401 | A valid credential is missing. | Get another credential and retry once if the operation is safe. |
403 | A policy, scope, permission, or context blocked the operation. | Review authorization and context. |
404 | The resource does not exist in the visible context. | Verify the identifier, store, and seller. |
409 | Current state conflicts with the operation. | Read the resource and decide from the new state. |
429 | A request-rate or concurrency limit was reached. | Honor Retry-After when present and wait. |
5xx | Temporary or internal failure. | Retry only when replaying the operation is safe. |
The endpoint reference defines the meaning of a specific code and its declared
responses.
Retries
A retryable status does not make the operation retryable. Before replaying, confirm the method is idempotent, an idempotency key exists, or you can check whether the first attempt completed.
function mayRetry(response: Response, canReplay: boolean) {
if (!canReplay) return false;
return response.status === 429 || response.status >= 500;
}Use exponential backoff with jitter and a maximum number of attempts. Do not
automatically retry a POST unless its contract documents idempotency.