REST API Error Response Format Checker

By · Updated

Paste a JSON API error response to score its structure out of 100, see which fields are missing, and copy a cleaner body as RFC 9457 problem+json or a custom envelope. Checks for status code, error code, message, request ID, timestamp, field details, a consistent wrapper, and an accidentally exposed stack trace. Runs entirely in your browser.

API error response checker

Examples
or press ⌘/Ctrl + Enter
80 / 100 Good

6 of 8 checks passed · 2 issues to fix

  • Pass

    HTTP status code

    Found "statusCode": 422.

  • Pass

    Machine-readable error code

    Found "code": "VALIDATION_ERROR".

  • Pass

    Human-readable message

    Found "message".

  • Missing

    Request / trace / instance ID

    No occurrence identifier. Add "requestId" / "traceId" (or RFC 9457's "instance") so users can quote it and you can find the matching log line.

  • Missing

    Timestamp

    No timestamp. Add an ISO-8601 "timestamp" so the error can be correlated with logs and metrics.

  • Pass

    Field validation details

    Found "details" with per-field entries.

  • Clean

    No exposed stack trace

    No stack trace or internal exception leaked to the client.

  • Pass

    Consistent error wrapper

    Errors are nested under a top-level "error" object — a consistent envelope.

Improved error format

{
  "type": "https://api.example.com/errors/validation-error",
  "title": "Unprocessable Entity",
  "status": 422,
  "detail": "The request body failed validation.",
  "instance": "/requests/req_8f3c2b1a9d4e",
  "errors": [
    {
      "pointer": "#/email",
      "detail": "Email is not a valid address."
    },
    {
      "pointer": "#/password",
      "detail": "Password must be at least 8 characters."
    }
  ]
}

RFC 9457 — serve with the application/problem+json content type.

What a good error response includes

The eight things this tool scores, and what each one is for. Field names are matched loosely — statusCode or status, message or detail, and so on.

Field What it does Example
statusCode Echo the HTTP status in the body so clients reading only the payload still know the category. 422
code A stable, machine-readable error code clients can branch on without parsing prose. "VALIDATION_ERROR"
message A human-readable summary for the developer reading logs — not shown to end users verbatim. "The request body failed validation."
requestId An occurrence ID the user can quote and you can grep for in logs — a request/trace ID, or RFC 9457's instance. "req_8f3c2b1a9d4e"
timestamp ISO-8601 time of the error, to line it up with logs and metrics. "2026-01-15T09:24:11Z"
details Per-field validation errors so a form can highlight each bad input. [{ field, message }]
(no stack) Never return stack traces or internal exceptions — they leak paths and internals. Log them server-side.
error wrapper Nest everything under one key (or use RFC 9457) so every error has the same shape. { "error": { … } }

API error handling in JavaScript

The most common mistake on the client is assuming fetch throws on an error status. It doesn't — it only rejects on a network failure, so a 500 resolves like a success. Check res.ok, then read the structured error body and turn it into a typed error your UI can act on.

async function request(url, options) {
  const res = await fetch(url, options);
  if (res.ok) return res.json();

  // fetch doesn't throw on 4xx/5xx — read the structured error body yourself.
  const body = await res.json().catch(() => ({}));
  const error = body.error ?? body; // unwrap the envelope if there is one

  throw new ApiError({
    status: res.status,
    code: error.code ?? "UNKNOWN",
    message: error.message ?? "Request failed",
    requestId: error.requestId ?? res.headers.get("x-request-id"),
    details: error.details ?? [],
  });
}

Because every error shares the same shape, this one helper covers every endpoint: unwrap body.error, read code and message, and keep the requestId so a user can quote it in a bug report. That consistency is exactly what the score above rewards.

Frequently asked

What should a REST API error response include?
At a minimum: an HTTP status code (echoed in the body as well as the status line), a stable machine-readable error code, and a human-readable message. Beyond that, a request or trace ID, a timestamp, and — for validation errors — a details array describing each bad field. Everything should sit inside a consistent wrapper so success and error responses are easy to tell apart. Crucially, never include a stack trace or internal exception in the response.
What is the best format for a REST API error body?
Two formats are widely used and both score well here. The envelope style nests everything under a top-level "error" object: { "error": { "code", "message", "statusCode", "requestId", "details" } }. The standardised alternative is RFC 9457 (problem+json), which puts "type", "title", "status", and "detail" at the root with an application/problem+json content type. JSON:API's top-level "errors" array is a third recognised option. Pick one and use it for every endpoint — consistency matters more than which one you choose.
Why is exposing a stack trace in an API response a problem?
A stack trace reveals file paths, framework versions, library internals, and sometimes query fragments or secrets — a gift to an attacker mapping your system, and noise for the client. Stack traces belong in your server logs, keyed by the same request ID you return to the client. This checker treats any stack, stackTrace, trace, or exception field in the body as a failed check.
How do I handle API error responses in JavaScript?
fetch only rejects on network failure, not on 4xx/5xx — so check res.ok yourself, then read the structured error body with res.json(). Pull error.code and error.message out of the envelope, attach the requestId (from the body or an x-request-id header), and throw a typed error your UI can react to. The 'API error handling in JavaScript' section on this page has a copy-paste example.
Should the HTTP status code be repeated in the response body?
It's good practice. The status line already carries it, but echoing it in the body (as statusCode or status) helps clients that log or queue the parsed body without the response object, makes fixtures self-describing, and matches RFC 9457, which includes a status member. It should always agree with the real HTTP status.
Does this checker send my API response anywhere?
No. Parsing, scoring, and the improved-format generation all run as JavaScript in your browser. Nothing is uploaded or stored, so you can safely paste responses from a production or internal API.
All tools →