# Errors
Source: https://docs.file.ai/api/errors

> Read fileAI API errors: RFC 9457 problem documents, stable error codes and request ids.

Production

# Errors

Copy pageCopy page

Read fileAI API errors: RFC 9457 problem documents, stable error codes and request ids.

Copy pageCopy page

Every error from the fileAI API is an [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) problem document, served as `Content-Type: application/problem+json`. Each one carries a stable `code` to branch on and a `requestId` to quote when you contact support.

## 

[​

](#how-it-works)

How it works

```
{
  "type": "https://errors.file.ai/validation-failed",
  "title": "Validation failed",
  "status": 422,
  "detail": "One or more fields are invalid.",
  "instance": "/prod/v1/files/upload",
  "code": "VALIDATION_FAILED",
  "requestId": "0f1c8e03-978e-40d5-bc93-6894a57f9324",
  "errors": [
    {
      "code": "REQUIRED",
      "detail": "fileName should not be empty",
      "pointer": "#/fileName"
    }
  ]
}
```

Branch on **`code`**, not on `detail` or `title`. Codes are a public contract: new ones can be added, but existing ones are never renamed or repurposed. `detail` is prose for humans and can change at any time. For unexpected server errors (`INTERNAL_ERROR`), `detail` is always the generic `An internal error occurred.` — the cause is in fileAI’s logs under your `requestId`.

### 

[​

](#request-ids)

Request ids

Every response, success or error, carries an `X-Request-Id` header, and errors repeat it as `requestId`. fileAI picks it in this order:

1.  The `X-Request-Id` header you sent, if any — so you can use your own correlation ids.
2.  The trace id from a W3C `traceparent` header, if you sent a valid one.
3.  A newly generated id.

### 

[​

](#rate-limits)

Rate limits

A `429 RATE_LIMITED` response includes a `retryAfter` member (seconds) and a `Retry-After` header with the same value. Responses also carry `RateLimit` and `RateLimit-Policy` headers, for example `"default";r=<remaining>;t=<seconds>`, so you can slow down before you hit the limit. See [Rate limits](/api/rate-limits) for every header.

## 

[​

](#example)

Example

Python

Node.js

```
import time, requests

def call(method, url, **kwargs):
    for attempt in range(5):
        r = requests.request(method, url, **kwargs)
        if r.ok:
            return r.json()
        problem = r.json()
        code = problem.get("code")
        if code == "RATE_LIMITED":
            time.sleep(problem.get("retryAfter", 1))
            continue
        if r.status_code >= 500:
            time.sleep(2 ** attempt)
            continue
        raise RuntimeError(f"{code}: {problem.get('detail')} (requestId {problem.get('requestId')})")
    raise RuntimeError("gave up after retries")
```

```
async function call(url, init) {
  for (let attempt = 0; attempt < 5; attempt++) {
    const res = await fetch(url, init);
    if (res.ok) return res.json();
    const problem = await res.json();
    if (problem.code === "RATE_LIMITED") {
      await new Promise((r) => setTimeout(r, (problem.retryAfter ?? 1) * 1000));
      continue;
    }
    if (res.status >= 500) {
      await new Promise((r) => setTimeout(r, 2 ** attempt * 1000));
      continue;
    }
    throw new Error(`${problem.code}: ${problem.detail} (requestId ${problem.requestId})`);
  }
  throw new Error("gave up after retries");
}
```

Send an [`Idempotency-Key`](/api/idempotency) on writes so that a retry can never apply the same change twice.

## 

[​

](#reference)

Reference

### 

[​

](#fields)

Fields

Field

Type

Description

`type`

string

URI for the problem type, e.g. `https://errors.file.ai/validation-failed`.

`title`

string

Stable, human-readable summary of the problem type.

`status`

number

The HTTP status, repeated.

`detail`

string

Explanation of this occurrence.

`instance`

string

The request path, including the `/prod` prefix, without the query string.

`code`

string

Stable machine-readable code. Branch on this.

`requestId`

string

Correlation id; same as the `X-Request-Id` header.

`errors`

array

Field-level violations. Empty when there are none.

`retryAfter`

number

Seconds until you may retry. On `429` only.

### 

[​

](#field-level-violations)

Field-level violations

Each entry in `errors` describes one problem with one field:

Field

Description

`code`

What kind of problem (see below).

`detail`

What was wrong, e.g. `fileName should not be empty`.

`pointer`

JSON Pointer to the body field, e.g. `#/fileName` or `#/parts/0/eTag`.

`parameter`

The query or header parameter, when the problem is not in the body.

Field `code`

Meaning

`REQUIRED`

A required value is missing or empty.

`INVALID_TYPE`

The value has the wrong type, e.g. a number where a string is expected.

`INVALID_VALUE`

The value isn’t one of the allowed options.

`INVALID`

Any other rule failed, such as a length or format limit.

### 

[​

](#error-codes)

Error codes

Code

HTTP status

Meaning

`BAD_REQUEST`

400

The request can’t be processed as sent — for example a missing required `Idempotency-Key`, an invalid cursor, or a bad `limit`.

`UNAUTHENTICATED`

401

The `x-api-key` header is missing or the key is invalid.

`FORBIDDEN`

403

The key is inactive or lacks access — for example, an agent call with a key that has no user.

`READONLY_KEY`

403

A read-only key was used on a write endpoint.

`FEATURE_DISABLED`

403

The feature this endpoint relies on isn’t enabled for the workspace. Nothing is wrong with the request.

`NOT_FOUND`

404

The resource doesn’t exist in this workspace.

`AGENT_RUN_IN_PROGRESS`

409

The agent session already has a turn running. Wait, or stop it, then ask again.

`IDEMPOTENT_REQUEST_IN_PROGRESS`

409

An earlier request with the same `Idempotency-Key` is still running.

`PAYLOAD_TOO_LARGE`

413

The upload or body is over the size limit.

`UNSUPPORTED_MEDIA_TYPE`

415

The file type isn’t accepted, or its content doesn’t match its declared type.

`VALIDATION_FAILED`

422

One or more fields are invalid. See `errors`.

`IDEMPOTENCY_KEY_REUSED`

422

The `Idempotency-Key` was already used with a different request body.

`INVALID_BATCH`

422

A batch upload contains no files.

`BATCH_TOO_LARGE`

422

A batch upload has more files than one batch allows.

`BATCH_PARTS_TOO_LARGE`

422

A multipart batch would need more parts than fit in one response. Send fewer files, or a larger `partSizeLimit`.

`INVALID_ID`

422

Per-item code in multipart batch results: the upload `id` is missing or blank.

`INVALID_KEY`

422

Per-item code in multipart batch results: the upload `key` is missing or blank.

`INVALID_PARTS`

422

Per-item code in multipart batch results: the part list is empty or was rejected by storage. Re-send the parts.

`RATE_LIMITED`

429

Too many requests. Wait `retryAfter` seconds.

`INTERNAL_ERROR`

500

Unexpected server-side failure. Safe to retry with backoff. Also used for other unmapped `5xx` statuses.

`UPSTREAM_ERROR`

502

A dependency fileAI called rejected the request or didn’t answer.

`SERVICE_UNAVAILABLE`

503

A required dependency isn’t configured, so the work was refused instead of being queued where it could never finish.

`INVALID_ID`, `INVALID_KEY` and `INVALID_PARTS` appear in `results[].error.code` of `POST /v1/files/upload/multipart/complete/batch`, not as a top-level error.

### 

[​

](#legacy-fields)

Legacy fields

Problem documents also carry three deprecated keys for integrations written before RFC 9457 errors:

Legacy field

Use instead

`message`

`detail` / `title`

`error`

`title`

`statusCode`

`status`

They will be removed in a future version. Migrate to `detail`, `title` and `status`.

### 

[​

](#when-to-retry)

When to retry

Status

Retry?

`429`

Yes, after `retryAfter` seconds.

`500`, `502`, `503`

Yes, with exponential backoff.

`409 IDEMPOTENT_REQUEST_IN_PROGRESS`, `409 AGENT_RUN_IN_PROGRESS`

Yes, once the earlier request or turn has finished.

`400`, `401`, `403`, `404`, `413`, `415`, `422`

No. Fix the request first; resending it unchanged returns the same error.

When you contact [support@file.ai](mailto:support@file.ai), include the `requestId` and `code`.

## 

[​

](#related)

Related

## Idempotent requests

Retry writes safely, and which errors are replayed.

## Pagination

Why a stale cursor returns `400`.

## Authentication and regions

API keys, read-only keys and base URLs.

## Versioning and deprecation

How changes and deprecations are signalled.

[Previous](/api/async-jobs)[

Rate limits

Read the rate-limit headers, handle a 429 and back off before you hit the limit.

Next

](/api/rate-limits)

⌘I

## On this page

*   [How it works](#how-it-works)
    *   [Request ids](#request-ids)
    *   [Rate limits](#rate-limits)
*   [Example](#example)
*   [Reference](#reference)
    *   [Fields](#fields)
    *   [Field-level violations](#field-level-violations)
    *   [Error codes](#error-codes)
    *   [Legacy fields](#legacy-fields)
    *   [When to retry](#when-to-retry)
*   [Related](#related)
