# Error Handling

The Kordiam API uses [RFC 9457 Problem Details](https://www.rfc-editor.org/rfc/rfc9457) for error responses. The response shape is consistent across the public API, while endpoint-specific status codes and validation rules remain documented in the [API reference](/api).

## Error Response Format

```json title="Problem Details response"
{
  "type": "https://docs.kordiam.app/docs/errors/validation-failed",
  "title": "Validation Failed",
  "status": 400,
  "detail": "Validation failed. Check the 'errors' array for details.",
  "instance": "/api/v2/elements",
  "traceId": "abc-123-def"
}
```

### Fields

| Field      | Type      | Description                                                            |
|------------|-----------|------------------------------------------------------------------------|
| `type`     | `string`  | URI identifying the error type. Use it as the primary machine-readable error category. |
| `title`    | `string`  | Short, human-readable summary of the error type.                       |
| `status`   | `integer` | HTTP status code.                                                      |
| `detail`   | `string`  | Specific explanation of what went wrong in this request.               |
| `instance` | `string`  | URI of the request that caused the error.                              |
| `traceId`  | `string`  | Correlation ID for log tracing. Include this when contacting support.  |

## Validation Errors

Validation errors (HTTP 400) include an additional `errors` array with field-level details:

```json title="Validation error response" showLineNumbers
{
  "type": "https://docs.kordiam.app/docs/errors/validation-failed",
  "title": "Validation Failed",
  "status": 400,
  "detail": "Validation failed. Check the 'errors' array for details.",
  "instance": "/api/v2/elements",
  "traceId": "abc-123-def",
  "errors": [
    {
      "scope": "path",
      "path": "id",
      "code": "range",
      "message": "must be greater than or equal to 1"
    }
  ]
}
```

### Validation Issue Fields

| Field     | Description                                                                                                                                        |
|-----------|----------------------------------------------------------------------------------------------------------------------------------------------------|
| `scope`   | Where the invalid input was found: `body`, `query`, `path`, `header`, or `global`                                                                  |
| `path`    | The field path (e.g., `title`, `tasks[0].status`). Null for `global` scope.                                                                        |
| `code`    | Stable machine-readable string describing the violated rule or constraint. Treat it as endpoint-specific metadata rather than a fixed global enum. |
| `message` | Human-readable description of the constraint violation.                                                                                            |

## Error Type Reference

The [Error Reference](/docs/errors/index) documents the error types currently supported as part of
the public client contract. Treat the reference as the place to learn what a `type` means, and treat
the [API reference](/api) as the source of truth for which status codes an endpoint documents.

New problem types may be added over time as the public contract grows. If a response uses an
unlisted `type`, handle it through the standard Problem Details fields and log `traceId` for support.

## Common Error Status Codes

| Status | Meaning                                                |
|--------|--------------------------------------------------------|
| `400`  | Bad Request - validation failure, malformed input      |
| `401`  | Unauthorized - missing or invalid authentication       |
| `403`  | Forbidden - authenticated but insufficient permissions where the endpoint exposes this outcome |
| `404`  | Not Found - resource does not exist                    |
| `405`  | Method Not Allowed - HTTP method not supported         |
| `406`  | Not Acceptable - unsupported `Accept` header           |
| `409`  | Conflict - resource state conflict                     |
| `415`  | Unsupported Media Type - wrong Content-Type            |
| `429`  | Too Many Requests - request was throttled              |
| `500`  | Internal Server Error - unexpected server error        |

## Best Practices

1. Always check the `type` field to programmatically identify the error category
2. For validation errors, iterate the `errors` array to display field-specific messages
3. Include the `traceId` when contacting support for faster resolution
4. Do not infer retry behavior from status code alone; retry only transient failures — `429 Too
   Many Requests` and `5xx` responses — honoring any `Retry-After` header
