# Error responses

Canonical page: https://docs.ovok.com/errors

Ovok's standard HTTP API errors use the [RFC 9457 Problem Details](https://www.rfc-editor.org/rfc/rfc9457) media type, `application/problem+json`. The response keeps the legacy fields used by existing clients while exposing a stable problem type, the HTTP status, a request path, a trace ID, and structured field errors.

## Response body [#response-body]

```json
{
  "type": "https://docs.ovok.com/errors/validation-failed",
  "status": 422,
  "detail": "The request has invalid fields.",
  "instance": "/v1/slim/patient",
  "traceId": "01JQEXAMPLE8D2A4B6C",
  "errors": [
    { "field": "email", "code": "FIELD_INVALID_EMAIL", "params": null }
  ],
  "statusCode": 422,
  "error": "Unprocessable Entity",
  "timestamp": "2026-10-22T00:00:00.000Z",
  "path": "/v1/slim/patient",
  "message": ["email must be an email"],
  "requestId": "request-id"
}
```

`type` is a stable URI for the error category. Its slug normally comes from the HTTP status mapping below; an endpoint may use a specific machine code instead. Use `status` for HTTP handling and `type` for category-specific handling. `detail` is human-readable and may be `null`; do not parse it for program logic. `instance` is the request path without its query string.

`traceId` identifies the request in Ovok's tracing and logs. It may be `null` when no trace context is available. Include it when reporting an error to support. The legacy `requestId`, `statusCode`, `error`, `timestamp`, `path`, and `message` fields are retained for existing clients during migration.

## Field errors [#field-errors]

`errors` is always an array in this response format. A field-level error contains:

| Field | Meaning |
| --- | --- |
| `field` | Request field or resource path; `null` when the error is not tied to one field. |
| `code` | Machine-readable reason for this field error, such as `FIELD_INVALID_EMAIL` or `FIELD_REQUIRED`. |
| `params` | Optional constraint values, or `null` when there are none. |

Correct the fields named by `errors` before retrying. The API limits the response to 100 field errors. These nested `errors[].code` values are field codes; they are separate from the top-level problem `type`.

## Stable status types [#stable-status-types]

When no endpoint-specific machine code is supplied, the problem type is `https://docs.ovok.com/errors/<slug>`. The pages below document the types mapped by the current Ovok core release.

| Status | Type |
| --- | --- |
| 400 | [`malformed-request`](/errors/malformed-request) |
| 401 | [`unauthenticated`](/errors/unauthenticated) |
| 403 | [`forbidden`](/errors/forbidden) |
| 404 | [`not-found`](/errors/not-found) |
| 405 | [`method-not-allowed`](/errors/method-not-allowed) |
| 406 | [`not-acceptable`](/errors/not-acceptable) |
| 408 | [`request-timeout`](/errors/request-timeout) |
| 409 | [`conflict`](/errors/conflict) |
| 410 | [`gone`](/errors/gone) |
| 412 | [`precondition-failed`](/errors/precondition-failed) |
| 413 | [`content-too-large`](/errors/content-too-large) |
| 415 | [`unsupported-media-type`](/errors/unsupported-media-type) |
| 422 | [`validation-failed`](/errors/validation-failed) |
| 423 | [`locked`](/errors/locked) |
| 424 | [`failed-dependency`](/errors/failed-dependency) |
| 428 | [`precondition-required`](/errors/precondition-required) |
| 429 | [`too-many-requests`](/errors/too-many-requests) |
| 500 | [`internal-error`](/errors/internal-error) |
| 501 | [`not-implemented`](/errors/not-implemented); a configured machine code may use [`feature-not-configured`](/errors/feature-not-configured) |
| 502 | [`upstream-error`](/errors/upstream-error) |
| 503 | [`service-unavailable`](/errors/service-unavailable) |
| 504 | [`upstream-timeout`](/errors/upstream-timeout) |
| Other 4xx | [`client-error`](/errors/client-error) |
| Other 5xx | [`server-error`](/errors/server-error) |

An endpoint can supply a stable machine code that replaces the status-derived type. The [endpoint-specific machine-code registry](/errors/machine-codes) lists all 64 types emitted by the audited core release, with one troubleshooting page per type. It was checked against merged `ovok-core` development commit `9a6ca1c2523079bcb8f7d4cbee583681c475d683`; update the registry and pages when a backend change adds or removes a type. Published HTTP endpoint error sections link their status values to the generic guidance and each listed machine code to its canonical page. Some backend operations have no dedicated public route page yet; their machine-code page remains the reference and links to the closest available guide where one exists.

## Protocol-specific errors [#protocol-specific-errors]

Not every Ovok API uses Problem Details. FHIR routes return a FHIR [`OperationOutcome`](/api/fhir/r4/operation-outcome); interpret its `issue` entries and expressions using the FHIR format. OAuth token endpoints and the MCP authorization flow keep their protocol-specific error members; the [account refresh route](/authentication/account/refresh-token) documents its own status outcomes. MCP authentication, JSON-RPC, and tool-call failures keep their distinct response bodies; see [MCP server troubleshooting](/working-with-ai-agents/mcp-server) and [MCP tools](/working-with-ai-agents/mcp-tools). GraphQL requests use the GraphQL `errors` response envelope; see the [GraphQL API guide](/graphql). Do not parse these protocol responses as Problem Details.

## Top-level `code` [#top-level-code]

Ovok does not currently add a top-level `code` member to Problem Details. The FhirStore client interprets a string top-level `code` as the complete error and can lose the rest of the response body. Use `type`, `status`, and the documented field errors instead. The nested `errors[].code` remains available for validation.
