> ## Documentation Index
> Fetch the complete documentation index at: https://developers.lighton.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# API Errors

> Error codes, response format, and troubleshooting for the LightOn API.

# API Errors

When an API request fails, all LightOn API returns a JSON error response with a consistent structure. Every error includes a machine-readable `error` code your application can use for programmatic handling, and a human-readable `detail` message for debugging.

## Error Response Format

All `/api/v3/` error responses share this envelope:

```json theme={null}
{
  "id": null,
  "code": 400,
  "error": "bad_request",
  "detail": "Unknown content type path: 'fake:path'",
  "doc_url": "https://developers.lighton.ai/errors#bad_request"
}
```

| Field     | Type                 | Description                                                                                                          |
| --------- | -------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `id`      | `string \| null`     | Resource or job identifier, when one exists at error time. `null` for most errors.                                   |
| `code`    | `integer`            | HTTP status code (mirrors the response status).                                                                      |
| `error`   | `string`             | Machine-readable error code. Use this for programmatic error handling.                                               |
| `detail`  | `string`             | Human-readable explanation. May change between versions — do not parse.                                              |
| `doc_url` | `string`             | Link to the relevant section of this page.                                                                           |
| `index`   | `integer` (optional) | 0-based position of the failing action in a batch request. Only present on errors from dedicated `/batch` endpoints. |

### Validation errors (422)

Requests that fail field-level validation return **422 Unprocessable Entity** with an additional `fields` key mapping each invalid field to its errors:

```json theme={null}
{
  "id": null,
  "code": 422,
  "error": "validation_error",
  "detail": "One or more fields failed validation.",
  "doc_url": "https://developers.lighton.ai/errors#validation_error",
  "fields": {
    "name": [
      {"error": "required", "detail": "Field required"}
    ],
    "attribute_type": [
      {"error": "invalid_choice", "detail": "Input should be 'text', 'number', 'date', 'boolean', 'select' or 'multi-select'"}
    ]
  }
}
```

Each entry in `fields` is an array of `{error, detail}` objects. A single field can have multiple errors. The `error` value is a [field error code](#field-error-codes) your application can map to form field states.

### Batch error responses

Dedicated batch endpoints (e.g., `POST /api/v3/content-types/batch`, `POST /api/v3/files/{id}/facets/batch`) execute multiple actions in one request. When a batch request fails, the error response includes an `index` field — the 0-based position of the action that caused the failure:

```json theme={null}
{
  "id": null,
  "code": 400,
  "error": "content_type_unknown",
  "detail": "Unknown content type path: 'fake:path'.",
  "doc_url": "https://developers.lighton.ai/errors#content_type_unknown",
  "index": 2
}
```

All error types (400, 403, 404, 422) include `index` when triggered inside a batch. Single-action requests never include this field.

**Replay safety:** actions before the failing index are committed but their results are not returned. All action verbs are idempotent — re-send the entire batch after fixing the failing action to complete it.

***

## HTTP Status Codes

| Status  | Meaning                                                                                     | Typical action                                                                 |
| ------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| **400** | Business rule violated — the request is structurally valid but the operation is not allowed | Read `error` and `detail` to understand the constraint. Fix the request logic. |
| **401** | Not authenticated — credentials are missing or expired                                      | Refresh your API key or session token.                                         |
| **403** | Forbidden — authenticated but lacking the required permission                               | Check your role and permissions for this resource.                             |
| **404** | Not found — the resource doesn't exist or isn't accessible to you                           | Verify the resource ID or path.                                                |
| **409** | Conflict — a resource with the same identifier already exists                               | Use a different name, or fetch the existing resource.                          |
| **422** | Validation error — one or more request fields are invalid                                   | Read `fields` to identify which fields to fix.                                 |
| **429** | Rate limited — too many requests                                                            | Wait and retry after the indicated period.                                     |
| **500** | Server error — something unexpected went wrong                                              | Retry later. If persistent, contact support.                                   |
| **502** | Upstream error — a dependent service (AI model, external provider) failed                   | Retry later. The `error` code indicates which service.                         |
| **503** | Service unavailable — a required service is not deployed or reachable                       | Retry later.                                                                   |
| **504** | Timeout — a dependent service did not respond in time                                       | Retry with a simpler request (fewer pages, shorter query).                     |

***

## Error Codes

### bad\_request

**Status:** 400

The request is structurally valid JSON but violates a domain rule. The `detail` message explains the specific constraint.

```json theme={null}
{"error": "bad_request", "detail": "Unknown content type path: 'fake:path'"}
```

Common causes:

* Invalid parameter combination
* Unsupported value for a domain-specific field
* Operation not applicable to the current resource state

***

### unauthorized

**Status:** 401

Authentication credentials were not provided or are invalid.

```json theme={null}
{"error": "unauthorized", "detail": "Authentication credentials were not provided."}
```

Include a valid API key in the `Authorization: Bearer <key>` header, or authenticate via session cookie.

***

### email\_verification\_required

**Status:** 403

Your email address has not been verified. Some operations require a verified email.

```json theme={null}
{"error": "email_verification_required", "detail": "Please verify your email address to access this feature."}
```

Check your inbox for a verification email, or request a new one from your account settings.

***

### insufficient\_permissions

**Status:** 403

You are authenticated but your role does not grant access to this operation.

```json theme={null}
{"error": "insufficient_permissions", "detail": "You do not have permission to perform this action."}
```

Contact your workspace or company administrator to request the required permission.

***

### not\_found

**Status:** 404

The requested resource does not exist, or you do not have access to it. For security, the API does not distinguish between "does not exist" and "not accessible."

```json theme={null}
{"error": "not_found", "detail": "Document not found."}
```

Verify the resource ID or path. If the resource was recently created, ensure you have the appropriate workspace membership.

***

### conflict

**Status:** 409

A resource with the same unique identifier (name, path, etc.) already exists.

```json theme={null}
{"error": "conflict", "detail": "A resource with this name already exists."}
```

Choose a different name, or retrieve the existing resource.

***

### content\_filtered

**Status:** 422

The model refused to generate a response, typically because a safety filter was triggered.

```json theme={null}
{
  "error": "content_filtered",
  "fields": {
    "query": [{"error": "content_filtered", "detail": "The model refused to generate an answer or a safety filter was triggered."}]
  }
}
```

Rephrase your query. This is not a rate limit — the model determined the content was not appropriate to answer.

***

### context\_length\_exceeded

**Status:** 422

The combined query and retrieved context exceed the model's maximum context window.

```json theme={null}
{
  "error": "context_length_exceeded",
  "fields": {
    "query": [{"error": "context_length_exceeded", "detail": "Query + retrieved context exceeds the model's context window."}]
  }
}
```

Reduce the number of documents in scope (use `workspace_id`, `tag_id`, or `file_id` filters), or shorten your query.

***

### validation\_error

**Status:** 422

The request body is valid JSON, but one or more fields failed validation. Check the `fields` key for per-field error details.

```json theme={null}
{
  "error": "validation_error",
  "fields": {
    "content_type_path": [{"error": "required", "detail": "Field required"}],
    "choices": [{"error": "invalid", "detail": "'choices' must be a non-empty list for select/multi-select attributes."}]
  }
}
```

See [Field Error Codes](#field-error-codes) for the vocabulary of field-level `error` values.

***

### too\_many\_requests

**Status:** 429

You have exceeded the rate limit for this endpoint. Wait before retrying.

```json theme={null}
{"error": "too_many_requests", "detail": "Too many requests. Please try again later."}
```

***

### internal\_server\_error

**Status:** 500

An unexpected error occurred on the server. This is not caused by your request.

```json theme={null}
{"error": "internal_server_error", "detail": "An unexpected error occurred. Please try again later."}
```

If the error persists, contact support with the timestamp and endpoint.

***

### model\_unavailable

**Status:** 502 / 503

The requested AI model is not reachable or not currently deployed.

```json theme={null}
{"error": "model_unavailable", "detail": "The requested model is currently unavailable."}
```

Retry after a short delay. If using a specific model name, verify it is supported via the models endpoint.

***

### model\_timeout

**Status:** 504

The AI model did not respond within the allowed time.

```json theme={null}
{"error": "model_timeout", "detail": "The model did not respond within the allowed time."}
```

Consider reducing the complexity of your request (shorter query, fewer documents in scope).

***

## Domain Error Codes

Some endpoints return domain-specific `error` codes for fine-grained error handling. Each code links directly from the `doc_url` in the error response.

### Extract

#### extraction\_failed

**Status:** 500

The extraction pipeline failed unexpectedly. Retry the request. If the error persists, contact support.

#### extraction\_timeout

**Status:** 504

Extraction did not complete within the allowed time. Try extracting fewer pages at a time.

#### extraction\_upstream\_error

**Status:** 502

An upstream service used during extraction returned an error. Retry after a short delay.

#### invalid\_page

**Status:** 400

The page specification is malformed. Use integer page numbers or valid ranges.

#### page\_out\_of\_range

**Status:** 400

The requested page number is outside the document's actual page range. Check the document's page count first.

### Facets

#### attribute\_name\_conflict

**Status:** 400

Attribute name is already defined on another node in the same content type tree. Attribute names must be unique across the entire tree (root to leaves).

#### attribute\_name\_reserved

**Status:** 400

Attribute name collides with a system-reserved name (e.g. `id`, `path`, `type`). Choose a different name.

#### attribute\_type\_immutable

**Status:** 400

Cannot change an attribute's type after creation. To change the type, delete the attribute with `undefine_attribute` and recreate it with the new type.

#### attribute\_value\_invalid

**Status:** 400

The value does not match the attribute's type or allowed choices. For `select` attributes, the value must be one of the defined choices. For `multi-select`, it must be an array of valid choices.

#### content\_type\_depth\_exceeded

**Status:** 400

Tree nesting exceeds the maximum allowed depth of 4 levels (e.g. `legal:contract:nda:mutual` is depth 4). Restructure your taxonomy to stay within this limit.

#### content\_type\_not\_assigned

**Status:** 404

The content type is not assigned to this document. Classify the document first with the `classify` action.

#### content\_type\_not\_found

**Status:** 404

Content type path does not exist for your company. Verify available paths with `GET /api/v3/content-types`. If you need to create it, use the `adopt` or `define_content_type` action.

#### content\_type\_sibling\_conflict

**Status:** 400

The document already has a content type from the same tree root. A document can hold at most one classification per tree. Unclassify the existing one first, then classify with the new path.

#### content\_type\_unknown

**Status:** 400

Content type code is not recognized. Verify available content types with `GET /api/v3/content-types/seed/templates`.

### Files

#### upload\_session\_expired

**Status:** 400

The upload session has expired. Create a new upload session and retry.

#### upload\_session\_not\_found

**Status:** 404

The upload session ID does not exist. Verify the session ID or create a new one.

### Parse

#### ambiguous\_input

**Status:** 400

Both a file upload and a document URL were provided in the same request. Provide one or the other, not both.

#### file\_rendering\_failed

**Status:** 500

The file could not be rendered to images before OCR processing. The file may be corrupted or in an unsupported variant.

#### invalid\_model

**Status:** 400

The requested vision-language model is not available. Check supported models via the models endpoint.

#### invalid\_page\_range

**Status:** 400

Page range is malformed or out of bounds. Ensure start page is less than end page and both are within the document's page count.

#### max\_pages\_exceeded

**Status:** 400 | **Also:** `/extract`

The document exceeds the maximum page count allowed for this operation. Process the document in smaller page ranges.

#### max\_pages\_per\_request\_exceeded

**Status:** 400

Too many pages requested in a single OCR call. Split into smaller page ranges.

#### missing\_input

**Status:** 400

Neither a file upload nor a document URL was provided. Provide one of them.

#### no\_file

**Status:** 400

The file upload field is empty or missing. Attach a file to the request.

#### ocr\_concurrent\_limit

**Status:** 429

Too many concurrent OCR requests are running. Wait and retry after a short delay.

#### unsupported\_file\_format

**Status:** 400

The file type is not supported for parsing. Check supported file types in the API documentation.

#### vlm\_error

**Status:** 502

The vision-language model returned an error while processing the document. Retry after a short delay.

#### vlm\_unavailable

**Status:** 503

The vision-language model is not reachable or not currently deployed. Retry after a short delay.

### Workspaces

#### datasource\_connection\_failed

**Status:** 400

Could not connect to the external data source with the provided credentials. Verify your credentials and network access, then retry.

#### googledrive\_folder\_inaccessible

**Status:** 400

The Google Drive folder cannot be accessed with the provided service account. Verify that the service account has read access to the folder.

#### sharepoint\_site\_not\_found

**Status:** 400

The SharePoint site does not exist or is not accessible with the provided credentials. Verify the `site_id` or `site_name` and tenant configuration.

#### unknown\_provider

**Status:** 400

The datasource type is not recognized. Supported types: `googledrive`, `sharepoint`, `servicenow`, `webscrapper`.

#### workspace\_already\_synced

**Status:** 400

The workspace is already connected to a datasource. A workspace can only have one datasource.

#### workspace\_has\_datasource

**Status:** 409

The workspace already has an active datasource import running.

#### workspace\_has\_documents

**Status:** 400

Cannot convert to a synced workspace because it already contains manually uploaded documents. Remove existing documents first or create a new workspace.

***

## Field Error Codes

When you receive a `422` response, each entry in the `fields` dict contains an `error` code from this vocabulary:

| Code             | Description                            | Example                                                                               |
| ---------------- | -------------------------------------- | ------------------------------------------------------------------------------------- |
| `required`       | Field is missing from the request body | `{"error": "required", "detail": "Field required"}`                                   |
| `blank`          | Field is present but empty string      | `{"error": "blank", "detail": "This field may not be blank."}`                        |
| `null`           | Field is present but null              | `{"error": "null", "detail": "This field may not be null."}`                          |
| `invalid`        | Wrong type or format                   | `{"error": "invalid", "detail": "Input should be a valid integer"}`                   |
| `invalid_choice` | Not one of the allowed values          | `{"error": "invalid_choice", "detail": "Input should be 'text', 'number' or 'date'"}` |
| `invalid_format` | Doesn't match the expected pattern     | `{"error": "invalid_format", "detail": "Invalid email format"}`                       |
| `too_short`      | String or array below minimum length   | `{"error": "too_short", "detail": "String should have at least 3 characters"}`        |
| `too_long`       | String or array exceeds maximum length | `{"error": "too_long", "detail": "String should have at most 255 characters"}`        |
| `too_small`      | Number below minimum value             | `{"error": "too_small", "detail": "Input should be greater than or equal to 1"}`      |
| `too_large`      | Number exceeds maximum value           | `{"error": "too_large", "detail": "Input should be less than or equal to 100"}`       |
| `already_exists` | Duplicate value                        | `{"error": "already_exists", "detail": "A group with this name already exists."}`     |
| `does_not_exist` | Referenced resource not found          | `{"error": "does_not_exist", "detail": "User with this ID does not exist."}`          |

### Handling field errors in your application

```python theme={null}
import requests

try:
    response = requests.post(
        "https://your-instance.lighton.ai/api/v3/content-types",
        headers={"Authorization": f"Bearer {api_key}"},
        json={"action": "define_attribute"},
    )

    if not response.ok:
        error = response.json()

        # Batch requests include the 0-based action index that failed
        if "index" in error:
            print(f"  Failed at batch action #{error['index']}")

        if error["error"] == "validation_error" and "fields" in error:
            # Per-field errors — collect for form display or logging
            for field, errors in error["fields"].items():
                for entry in errors:
                    print(f"  {field}: [{entry['error']}] {entry['detail']}")
        else:
            # Domain error (e.g. attribute_type_immutable, content_type_not_found)
            print(f"Error {error['code']}: [{error['error']}] {error['detail']}")
except requests.RequestException as exc:
    print(f"Network error: {exc}")
```
