Web Development
API Error Handling That Users Can Trust
8 min read

Users do not experience a 502 or a timeout as an infrastructure detail. They experience uncertainty: did the order save, was the card charged, and should they press the button again?
Separate error categories
Validation errors, authentication failures, missing resources, conflicts, rate limits, provider outages, and unexpected server errors need different responses. Give each category a stable machine-readable code and a safe human message.
Log the detailed cause with a correlation identifier, but do not expose stack traces, database details, or secrets to the browser. The customer-facing message should focus on status and recovery.
- Use appropriate HTTP status codes
- Return a stable error code beside the message
- Include a support-safe reference identifier
- Avoid leaking provider responses directly
Design retries deliberately
Read requests can often retry with exponential backoff. Writes require more care because the first attempt may have succeeded even when the response was lost. Use idempotency keys or unique business references for operations such as orders, payments, and email jobs.
Set timeouts instead of waiting forever, and define which layer owns a retry. If the browser, API, job queue, and provider client all retry independently, one incident can multiply traffic.
- Retry only transient failures
- Add jitter so clients do not retry together
- Cap attempts and route exhausted work for review
- Make duplicate writes safe before enabling retries
Show the truth in the interface
Use explicit pending states for work whose outcome is not yet known. Let users revisit the status with a durable reference. A generic red toast that disappears after three seconds is not enough for an important transaction.
Track error rates by operation and provider, not only global server errors. Alert on customer impact and include the same reference support staff can search.