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

# Errors

> Error codes, HTTP status codes, and resolution guidance for all Gloo AI API endpoints.

When interacting with the Gloo AI API, error handling depends on whether the response is non-streaming or streaming. For non-streaming responses, check the HTTP status code and parse the JSON response body. For streaming Completions responses, the initial response is `200 text/event-stream`; once streaming has started, later failures are delivered as Server-Sent Events instead of non-2xx HTTP responses.

For AI error objects, `error.code` is the numeric internal code, such as `2001`, and `error.name` is the symbolic code, such as `PROVIDER_TIMEOUT`.

## Quick Reference

<CardGroup cols={3}>
  <Card title="HTTP Status Codes" icon="list" href="#http-status-codes">
    Full table of every HTTP status returned by active endpoints.
  </Card>

  <Card title="Error Code Reference" icon="code" href="#error-code-reference">
    Exact error codes from the API with resolution guidance.
  </Card>

  <Card title="AI Error Object" icon="brackets-curly" href="#ai-error-object">
    Field reference for enriched Completions errors.
  </Card>

  <Card title="Streaming Errors" icon="radio" href="#streaming-errors">
    How errors are delivered after an SSE stream has started.
  </Card>

  <Card title="Authentication Errors" icon="lock" href="#authentication-errors">
    401 and 403 errors — missing tokens, expired credentials, permission issues.
  </Card>

  <Card title="Rate Limiting" icon="gauge" href="#rate-limiting-429">
    429 responses and how to implement retry logic with exponential backoff.
  </Card>

  <Card title="Endpoint-Specific Errors" icon="webhook" href="#endpoint-specific-errors">
    Error details for Completions, Ingestion, Content Controls, and Search.
  </Card>

  <Card title="Best Practices" icon="shield-check" href="#error-handling-best-practices">
    Patterns for reliable error handling across all endpoints.
  </Card>
</CardGroup>

## HTTP Status Codes

| Status Code                 | Meaning             | When You'll See It                                                                                           |
| --------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------ |
| `200 OK`                    | Success             | The request completed successfully.                                                                          |
| `400 Bad Request`           | Bad Request         | Missing required fields, wrong content type, or structurally invalid JSON.                                   |
| `401 Unauthorized`          | Unauthorized        | `Authorization` header missing, token expired, or required JWT claims (`sub`, `scope`) absent.               |
| `403 Forbidden`             | Forbidden           | Authorization was present but invalid, insufficient, or not allowed for the resource or publisher.           |
| `404 Not Found`             | Not Found           | Requested resource (item, publisher, collection) does not exist or was deleted.                              |
| `408 Request Timeout`       | Request Timeout     | Model provider did not respond within the allowed window. Retry with backoff.                                |
| `422 Unprocessable Entity`  | Validation Error    | Well-formed JSON that fails semantic validation — invalid enum, out-of-range value, business rule violation. |
| `429 Too Many Requests`     | Rate Limited        | Exceeded request rate or spending limit for your plan. Retry after `X-RateLimit-Reset`.                      |
| `500 Internal Server Error` | Server Error        | Unexpected error on the Gloo platform. Retry with backoff.                                                   |
| `502 Bad Gateway`           | Upstream Error      | Returned when a Content Controls vector-store update fails.                                                  |
| `503 Service Unavailable`   | Service Unavailable | Gloo service or upstream provider temporarily unavailable. Retry with backoff.                               |

***

## Error Code Reference

| Code / Name                          | HTTP Status                        | Description                                                                                                                                                                                    | Resolution                                                                                                                      |
| ------------------------------------ | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `unauthorized_missing_authorization` | 401                                | `Authorization` header is absent.                                                                                                                                                              | Add `Authorization: Bearer <token>` to all requests.                                                                            |
| `forbidden`                          | 403                                | Authorization was present but invalid, insufficient, or not allowed for the resource or publisher.                                                                                             | Verify the bearer token format and value; check API credential scopes and publisher access.                                     |
| `publisher_not_found`                | 400                                | Publisher ID does not exist.                                                                                                                                                                   | Verify the `publisher_id` value in the request.                                                                                 |
| `publisher_mismatch`                 | 403                                | Item does not belong to the specified publisher.                                                                                                                                               | Check that the `publisher_id` matches the item's original publisher.                                                            |
| `item_not_found`                     | 404                                | Requested item does not exist or was deleted.                                                                                                                                                  | Verify `item_id` or `producer_id`. Use list endpoints to confirm existence.                                                     |
| `item_publisher_mismatch`            | 403                                | Item does not belong to the specified publisher.                                                                                                                                               | Verify `publisher_id` and `item_id` belong to the same publisher.                                                               |
| `too_many_files`                     | 400                                | Producer ID is per-file only; multiple files submitted.                                                                                                                                        | Submit one file per `producer_id`.                                                                                              |
| `file_read_error`                    | 400                                | Uploaded file could not be decoded or read.                                                                                                                                                    | Verify the file is valid and not corrupt before uploading.                                                                      |
| `missing_producer_ids`               | 400                                | No `producer_id` values provided.                                                                                                                                                              | Include at least one `producer_id` in the request.                                                                              |
| `duplicate_content`                  | 200 result state                   | Content already ingested. Public response exposes the `duplicates` array alongside `ingesting`.                                                                                                | No action needed if re-ingestion is unintentional. To update, delete or patch the existing item.                                |
| `validation_error`                   | 422                                | One or more fields failed semantic validation.                                                                                                                                                 | Inspect the `detail` array: `loc` = field path, `msg` = reason, `input` = value you sent.                                       |
| `1001 / INVALID_REQUEST`             | 400                                | Request is structurally invalid — missing user message or invalid routing configuration.                                                                                                       | Fix the request body; for Completions V2, specify exactly one routing mode (`auto_routing`, `model`, or `model_family`).        |
| `1002 / CONTEXT_LENGTH_EXCEEDED`     | 400                                | Input exceeds model's maximum context window.                                                                                                                                                  | Shorten message history, reduce system prompt, or switch to a model with a larger context window.                               |
| `1003 / UNSUPPORTED_MODEL`           | 400 or stream event                | Requested model is not recognized or unavailable in this environment.                                                                                                                          | Use a supported model from the Models endpoint.                                                                                 |
| `1005 / SPENDING_LIMIT_EXCEEDED`     | 429                                | Spending limit reached for your plan.                                                                                                                                                          | Check billing limits; retry only after the limit condition is resolved.                                                         |
| `2001 / PROVIDER_TIMEOUT`            | 408 or stream event                | Model provider did not respond in time.                                                                                                                                                        | Retry with exponential backoff; consider a different model or routing mode if persistent.                                       |
| `2002 / PROVIDER_UNAVAILABLE`        | 503 or stream event                | Provider or backing service unavailable.                                                                                                                                                       | Retry with exponential backoff.                                                                                                 |
| `2003 / CONNECTION_ERROR`            | Stream event                       | Connection to the upstream provider was lost after streaming started.                                                                                                                          | Retry if `error.retryable` is `true`.                                                                                           |
| `2004 / RATE_LIMIT`                  | Stream event                       | Upstream provider rate limit was reached after streaming started.                                                                                                                              | Retry with exponential backoff.                                                                                                 |
| `2005 / PROVIDER_CONTENT_FILTER`     | 422 or content-filter stream event | Provider moderated the response.                                                                                                                                                               | Adjust the request or user-facing workflow; do not retry unchanged.                                                             |
| `2007 / EMPTY_STREAM`                | Stream event                       | Provider opened a stream but delivered no content chunks.                                                                                                                                      | Retry with exponential backoff.                                                                                                 |
| `2008 / PROVIDER_BAD_REQUEST`        | Stream event                       | Upstream provider rejected the request after streaming started.                                                                                                                                | Inspect the request and model requirements; retry only after correcting the request.                                            |
| `2011 / MALFORMED_SSE`               | Stream event                       | Upstream provider sent a malformed SSE frame.                                                                                                                                                  | Retry with exponential backoff.                                                                                                 |
| `2013 / PROVIDER_INFERENCE_ERROR`    | 500                                | Unexpected model inference failure.                                                                                                                                                            | Retry with exponential backoff and log `trace_id` if present in the response.                                                   |
| `3001 / INTERNAL_ERROR`              | 500 or stream event                | Unexpected error. The same code covers both retryable provider anomalies (`fault: "provider"`, `retryable: true`) and non-retryable platform errors (`fault: "internal"`, `retryable: false`). | Branch on `error.retryable` and `error.fault`, never on the code alone; log `trace_id`.                                         |
| `3003 / PROVIDER_AUTH_ERROR`         | Stream event                       | Upstream provider credentials are misconfigured.                                                                                                                                               | Treat as a platform issue; log `trace_id` and contact support if persistent.                                                    |
| `3004 / ROUTING_ERROR`               | Stream event                       | Platform routed the request to an endpoint that does not recognize the model.                                                                                                                  | Try a different model or routing mode; log `trace_id` if persistent.                                                            |
| `too_many_requests`                  | 429                                | Request rate limit exceeded.                                                                                                                                                                   | Wait for the `X-RateLimit-Reset` header value; implement exponential backoff. See [Rate Limits](/api-reference/general/limits). |

***

## AI Error Object

Completions errors include an enriched top-level `error` object. Use it for programmatic handling instead of parsing human-readable messages.

```json theme={null}
{
  "error": {
    "message": "The provider did not respond in time. Please try again.",
    "type": "timeout_error",
    "code": 2001,
    "name": "PROVIDER_TIMEOUT",
    "category": "provider_error",
    "description": "The upstream model provider did not respond within the allowed time window.",
    "fault": "provider",
    "retryable": true,
    "trace_id": "trace-id"
  }
}
```

| Field         | Description                                                            |
| ------------- | ---------------------------------------------------------------------- |
| `message`     | Request-specific customer-facing error message.                        |
| `type`        | Stable wire-format error type.                                         |
| `code`        | Numeric internal error code.                                           |
| `name`        | Symbolic error name for programmatic branching and alerting.           |
| `category`    | Broad category: `client_error`, `provider_error`, or `platform_error`. |
| `description` | Stable explanation of what the error code means.                       |
| `fault`       | Responsible party: `client`, `provider`, or `internal`.                |
| `retryable`   | Whether retrying the same request may succeed.                         |
| `trace_id`    | Trace identifier to include in support requests when present.          |

<Tip>
  Use `error.retryable` for retry decisions, `error.name` or `error.code` for branching, and `trace_id` for debugging with support.
</Tip>

## Common Error Scenarios

### Authentication Errors

These errors occur when there is an issue with your bearer token or the permissions associated with your API credentials.

#### 401 Unauthorized — Missing or Invalid Token

Returned when the `Authorization` header is missing from the request.

```json theme={null}
{
  "error": "Missing Authorization",
  "code": "unauthorized_missing_authorization"
}
```

Some Completions endpoints may return an app-level invalid-token response:

```json theme={null}
{
  "detail": "Invalid or expired access token."
}
```

Search endpoints can be rejected earlier by the gateway. When the `Authorization` header is present but malformed or the bearer token is invalid, the gateway returns `403` with the `forbidden` code.

#### 403 Forbidden — Insufficient Permissions

Returned when the request includes authorization, but the caller does not have permission for the requested resource or publisher, or the gateway rejects the authorization header.

```json theme={null}
{
  "error": "Forbidden - insufficient permissions",
  "code": "forbidden"
}
```

<Info>
  For the Ingestion API, a 403 most commonly means the `publisher_id` doesn't belong to your organization, or the item you are referencing does not belong to the specified publisher.
</Info>

***

### Validation Errors (400 / 422)

These errors indicate a problem with the parameters or body of your request. `400 Bad Request` signals a structurally invalid request, while `422 Unprocessable Entity` signals valid JSON that fails field-level validation.

#### Missing Required Field

Returned when a required body field is absent. Example: `model` is required when specifying direct model routing for Completions V2.

```json theme={null}
{
  "detail": [
    { "type": "missing", "loc": ["body", "model"], "msg": "Field required", "input": {} }
  ]
}
```

#### Invalid Routing Configuration

Completions V2 returns this as `400` when more than one — or no — routing mechanism is specified.

```json theme={null}
{
  "detail": "Exactly one routing mechanism (auto_routing, model, or model_family) must be specified."
}
```

#### Invalid Data Type

Returned when a field receives a value of the wrong type. Example: `certainty` expects a float.

```json theme={null}
{
  "detail": [
    { "type": "float_parsing", "loc": ["body", "certainty"], "msg": "Input should be a valid number", "input": "high" }
  ]
}
```

***

### Resource Not Found (404)

Returned when the requested item does not exist or has been permanently deleted.

```json theme={null}
{
  "code": "Item not found",
  "item_id": "c68c9303-9851-476e-96af-aa5bdd385811",
  "message": "The requested item does not exist or has been permanently deleted"
}
```

<Info>
  Publisher not found and invalid collection cases return `400`, not `404`. See [Ingestion](#ingestion) and [Search & Recommendations](#search-%26-recommendations) for these examples.
</Info>

***

### Duplicate Upload Results

#### Duplicate Content (Ingestion)

When files are submitted that were already ingested, the API returns `200 OK` with a `duplicates` array in the response body — this is not an HTTP error.

```json theme={null}
{
  "success": true,
  "message": "File processing started in background.",
  "ingesting": [],
  "duplicates": ["c999008e-de60-495c-8c9f-6a4b59cdb04b"]
}
```

<Info>
  Duplicates are returned in the response body, not as a `409 Conflict` error.
</Info>

***

### Rate Limiting (429)

Returned when you exceed the request rate limit for your plan.

```json theme={null}
{
  "error": "Rate limit exceeded",
  "code": "too_many_requests"
}
```

For Completions endpoints, a spending limit response includes additional error detail:

```json theme={null}
{
  "detail": {
    "message": "Spending limit reached",
    "code": "SPENDING_LIMIT_EXCEEDED"
  },
  "error": {
    "message": "Spending limit reached",
    "type": "rate_limit_error",
    "code": 1005,
    "name": "SPENDING_LIMIT_EXCEEDED",
    "category": "client_error",
    "description": "The account's spending limit has been reached.",
    "fault": "client",
    "retryable": false,
    "trace_id": "trace-id"
  }
}
```

**Rate limit response headers:**

| Header                  | Description                                  |
| ----------------------- | -------------------------------------------- |
| `X-RateLimit-Limit`     | Total requests allowed in the current window |
| `X-RateLimit-Remaining` | Requests remaining in the current window     |
| `X-RateLimit-Reset`     | Unix timestamp when the window resets        |

<Info>
  See [Rate Limits](/api-reference/general/limits) for exponential backoff pseudocode examples.
</Info>

***

### Server Errors (5xx)

<Warning>
  Only retry `408`, `429`, and `5xx` responses. Do not retry other `4xx` errors — they indicate a request problem that won't resolve on retry.
</Warning>

#### 500 Internal Server Error

An unexpected error occurred on the Gloo platform or during model inference. Retry with exponential backoff.

```json theme={null}
{
  "detail": "An unexpected error occurred during model inference. Please try again.",
  "error": {
    "message": "An unexpected error occurred during model inference. Please try again.",
    "type": "internal_error",
    "code": 2013,
    "name": "PROVIDER_INFERENCE_ERROR",
    "category": "provider_error",
    "description": "An unexpected error occurred during model inference at the upstream provider.",
    "fault": "provider",
    "retryable": true,
    "trace_id": "trace-id"
  }
}
```

#### 502 Bad Gateway

Returned by Content Controls endpoints when a vector-store update fails in the underlying data store.

```json theme={null}
{
  "detail": {
    "code": "Weaviate update failed",
    "message": "Postgres not modified due to vector store update failure",
    "weaviate_error": "Weaviate update failed"
  }
}
```

#### 503 Service Unavailable

The upstream provider or backing service is temporarily unavailable. Retry with exponential backoff.

```json theme={null}
{
  "detail": "The provider is currently unavailable. Please try again later.",
  "error": {
    "message": "The provider is currently unavailable. Please try again later.",
    "type": "service_unavailable_error",
    "code": 2002,
    "name": "PROVIDER_UNAVAILABLE",
    "category": "provider_error",
    "description": "The upstream model provider is temporarily unavailable.",
    "fault": "provider",
    "retryable": true,
    "trace_id": "trace-id"
  }
}
```

***

## Streaming Errors

When `stream=true` on Completions endpoints, the response starts as `200 text/event-stream`. After the SSE headers have been sent, the API cannot change the HTTP status code. Stream-time failures are therefore sent as SSE events.

A stream error event has `choices[0].finish_reason` set to `"error"` and includes the same enriched top-level `error` object used by non-streaming Completions errors.

```json theme={null}
{
  "id": "chatcmpl-error-abc123",
  "object": "chat.completion.chunk",
  "created": 1769792268,
  "model": "gloo-anthropic-claude-sonnet-4.6",
  "choices": [
    {
      "delta": {
        "content": null,
        "role": null
      },
      "finish_reason": "error",
      "index": 0
    }
  ],
  "error": {
    "message": "Stream connection dropped",
    "type": "connection_error",
    "code": 2003,
    "name": "CONNECTION_ERROR",
    "category": "provider_error",
    "description": "The connection to the upstream model provider was lost or could not be established.",
    "fault": "provider",
    "retryable": true,
    "trace_id": "trace-id"
  }
}
```

Stream-time error scenarios include provider timeout, provider rate limit, provider `5xx`, provider bad request, provider auth failure, routing error, unsupported model, empty stream, provider unavailable, malformed provider SSE, connection drop, and internal platform error.

<Info>
  If a stream error event includes `error.retryable: true`, retry with exponential backoff. If `error.retryable` is `false`, retry only after changing the request or model selection.
</Info>

For retry ceilings, application-level continuation after partial output, and the UX decisions around interrupted streams, see [Handling Streaming Failures](/best-practices/completions-streaming-failures).

### Content Filter During Streaming

Content moderation during streaming is represented differently from other stream errors. It does not emit a top-level `error` object. Instead, the stream sends a final assistant content event and then a terminal event with `finish_reason: "content_filter"`.

```json theme={null}
{
  "id": "chatcmpl-stream-abc123",
  "object": "chat.completion.chunk",
  "created": 1769792268,
  "model": "gloo-anthropic-claude-sonnet-4.6",
  "choices": [
    {
      "delta": {
        "content": ""
      },
      "finish_reason": "content_filter",
      "index": 0
    }
  ],
  "service_tier": null,
  "usage": null
}
```

Do not retry content-filter terminations unchanged. Adjust the user-facing workflow or request content.

### Grounded Streaming Citations

For Grounded Completions, when `stream=true`, `include_citations=true`, and citations are available, the first SSE event may contain a `citations` array before model content begins. This is a normal `200` stream event, not an error.

```json theme={null}
{
  "citations": [
    {
      "item_title": "Daily Prayer",
      "item_url": "https://www.studio.ai.gloo.com",
      "author": ["John Doe"],
      "publisher": "The Publisher",
      "publication_date": "Apr 08 2017",
      "snippets": [
        "Daily prayer is an essential part of life as...",
        "Making time to spend with the Lord is..."
      ]
    }
  ]
}
```

***

## Endpoint-Specific Errors

### Completions V2

<Card title="Completions V2 Reference" icon="bolt" href="/api-reference/completions/v2">
  POST /ai/v2/chat/completions
</Card>

The endpoint reference documents both `application/json` responses for non-streaming requests and `text/event-stream` responses for `stream=true`.

**Invalid Routing Configuration — 400**

Specify exactly one of `auto_routing`, `model`, or `model_family` per request.

```json theme={null}
{
  "detail": "Exactly one routing mechanism (auto_routing, model, or model_family) must be specified."
}
```

**Invalid Request — 400**

Returned when no user message is found in the `messages` array.

```json theme={null}
{
  "detail": "No user message found in the request.",
  "error": {
    "message": "No user message found in the request.",
    "type": "invalid_request_error",
    "code": 1001,
    "name": "INVALID_REQUEST",
    "category": "client_error",
    "description": "The request is malformed or contains invalid parameters.",
    "fault": "client",
    "retryable": false,
    "trace_id": "trace-id"
  }
}
```

**Messages Array Missing — 422**

The `messages` field is required. An absent `messages` array returns a validation error.

```json theme={null}
{
  "detail": [
    { "type": "missing", "loc": ["body", "messages"], "msg": "Field required", "input": {} }
  ]
}
```

**Context Window Exceeded — 400**

```json theme={null}
{
  "detail": {
    "message": "Input exceeds the model context window.",
    "type": "context_window_exceeded",
    "code": "context_length_exceeded",
    "model": "gloo-anthropic-claude-sonnet-4.6",
    "max_input_tokens": 1000000,
    "suggestion": "Use a model with larger context window such as gloo-anthropic-claude-sonnet-4.6 (1M tokens)"
  },
  "error": {
    "message": "Input exceeds the model context window.",
    "type": "invalid_request_error",
    "code": 1002,
    "name": "CONTEXT_LENGTH_EXCEEDED",
    "category": "client_error",
    "description": "The total token count of the request exceeds the model's context window.",
    "fault": "client",
    "retryable": false,
    "trace_id": "trace-id",
    "model": "gloo-anthropic-claude-sonnet-4.6",
    "max_input_tokens": 1000000,
    "suggestion": "Use a model with larger context window such as gloo-anthropic-claude-sonnet-4.6 (1M tokens)"
  }
}
```

**Provider Timeout — 408**

```json theme={null}
{
  "detail": "The provider did not respond in time. Please try again.",
  "error": {
    "message": "The provider did not respond in time. Please try again.",
    "type": "timeout_error",
    "code": 2001,
    "name": "PROVIDER_TIMEOUT",
    "category": "provider_error",
    "description": "The upstream model provider did not respond within the allowed time window.",
    "fault": "provider",
    "retryable": true,
    "trace_id": "trace-id"
  }
}
```

**Provider Content Filter — 422**

```json theme={null}
{
  "detail": "The provider moderated the response.",
  "error": {
    "message": "The provider moderated the response.",
    "type": "content_filter_error",
    "code": 2005,
    "name": "PROVIDER_CONTENT_FILTER",
    "category": "provider_error",
    "description": "The response was blocked by the upstream provider's content filter.",
    "fault": "provider",
    "retryable": false,
    "trace_id": "trace-id"
  }
}
```

**Provider Inference Error — 500**

```json theme={null}
{
  "detail": "An unexpected error occurred during model inference. Please try again.",
  "error": {
    "message": "An unexpected error occurred during model inference. Please try again.",
    "type": "internal_error",
    "code": 2013,
    "name": "PROVIDER_INFERENCE_ERROR",
    "category": "provider_error",
    "description": "An unexpected error occurred during model inference at the upstream provider.",
    "fault": "provider",
    "retryable": true,
    "trace_id": "trace-id"
  }
}
```

**Provider Unavailable — 503**

```json theme={null}
{
  "detail": "The provider is currently unavailable. Please try again later.",
  "error": {
    "message": "The provider is currently unavailable. Please try again later.",
    "type": "service_unavailable_error",
    "code": 2002,
    "name": "PROVIDER_UNAVAILABLE",
    "category": "provider_error",
    "description": "The upstream model provider is temporarily unavailable.",
    "fault": "provider",
    "retryable": true,
    "trace_id": "trace-id"
  }
}
```

***

### Grounded Completions

<Card title="Grounded Completions Reference" icon="bolt" href="/api-reference/completions/v2/grounded">
  POST /ai/v2/chat/completions/grounded
</Card>

Grounded Completions inherits all [Completions V2](#completions-v2) error responses, including routing configuration errors, context length exceeded, provider timeout, content filter, inference error, and provider unavailable.

The endpoint reference documents both `application/json` responses for non-streaming requests and `text/event-stream` responses for `stream=true`. For streaming grounded responses, citations may be emitted as the first stream event when `include_citations=true`.

**No Relevant Content Retrieved — 200**

Zero results is not an error — it means no retrieved content exceeded the certainty threshold. The response returns `200 OK` with `"sources_returned": false`. Lower `certainty` toward `0.5` or verify that content has been ingested.

***

### Ingestion

<Card title="Ingestion V2 Reference" icon="upload" href="/api-reference/ingestion/v2">
  POST /ingestion/v2/files
</Card>

**Publisher Not in Organization — 403**

Returned when the item or publisher does not belong to your organization.

```json theme={null}
{
  "detail": {
    "message": "Item does not belong to this publisher",
    "code": "publisher_mismatch"
  }
}
```

**Missing Authorization — 401**

Returned by the gateway when the `Authorization` header is missing.

```json theme={null}
{
  "error": "Missing Authorization",
  "code": "unauthorized_missing_authorization"
}
```

**Publisher Not Found — 400**

```json theme={null}
{
  "detail": {
    "message": "Publisher not found",
    "code": "publisher_not_found"
  }
}
```

**Producer ID with Multiple Files — 400**

```json theme={null}
{
  "detail": {
    "message": "Too many files. Producer ID is pre-file only.",
    "code": "too_many_files"
  }
}
```

**File Read Error — 400**

```json theme={null}
{
  "detail": {
    "message": "Could not read sermon.pdf: unable to decode uploaded file",
    "code": "file_read_error"
  }
}
```

**Duplicate Content — 200 Response**

Duplicate files appear in the `duplicates` array of a successful `200 OK` response, not as an HTTP error. See [Duplicate Upload Results](#duplicate-upload-results).

***

### Content Controls (Data Engine)

<CardGroup cols={2}>
  <Card title="Single Item Patch" icon="pen" href="/api-reference/content-controls/single-item-patch">
    PATCH /engine/v2/item
  </Card>

  <Card title="Multi-Item Patch" icon="pen-to-square" href="/api-reference/content-controls/multi-item-patch">
    PATCH /engine/v2/items
  </Card>

  <Card title="Delete Items" icon="trash" href="/api-reference/content-controls/delete-item">
    DELETE /engine/v2/items
  </Card>

  <Card title="Get Item Metadata" icon="magnifying-glass" href="/api-reference/content-controls/get-item-metadata">
    GET /engine/v2/items/{item_id}
  </Card>

  <Card title="Get Item by Producer ID" icon="magnifying-glass" href="/api-reference/content-controls/get-item-by-producer-id">
    POST /engine/v2/publisher/{publisher_id}/items/by-producer
  </Card>
</CardGroup>

**Item Not Found — 404**

```json theme={null}
{
  "code": "Item not found",
  "item_id": "c68c9303-9851-476e-96af-aa5bdd385811",
  "message": "The requested item does not exist or has been permanently deleted"
}
```

For items looked up by `producer_id`:

```json theme={null}
{
  "detail": {
    "code": "Items not found",
    "message": "No items were found for the provided producer IDs"
  }
}
```

**Publisher Not Found — 400**

```json theme={null}
{
  "detail": {
    "code": "publisher_not_found",
    "message": "Publisher not found"
  }
}
```

**Publisher / Item Ownership Mismatch — 403**

```json theme={null}
{
  "detail": {
    "code": "item_publisher_mismatch",
    "message": "Item does not belong to the specified publisher"
  }
}
```

Unauthorized delete attempt:

```json theme={null}
{
  "detail": {
    "code": "Unauthorized access",
    "message": "You don't have permission to delete these items",
    "unauthorized_items": ["c68c9303-9851-476e-96af-aa5bdd385811"]
  }
}
```

**Vector-Store Update Failure — 502**

Returned by the single-item PATCH endpoint when the vector store update fails.

```json theme={null}
{
  "detail": {
    "code": "Weaviate update failed",
    "message": "Postgres not modified due to vector store update failure",
    "weaviate_error": "Weaviate update failed"
  }
}
```

**Batch / Request Validation — 400**

Missing patch operations:

```json theme={null}
{
  "detail": {
    "code": "Invalid request",
    "message": "At least one patch operation is required"
  }
}
```

Missing item IDs in a delete request:

```json theme={null}
{
  "detail": {
    "code": "Invalid request",
    "message": "At least one item_id is required"
  }
}
```

Missing producer IDs:

```json theme={null}
{
  "detail": {
    "code": "Invalid request",
    "message": "At least one producer_id must be provided"
  }
}
```

***

### Search & Recommendations

<CardGroup cols={2}>
  <Card title="Search" icon="magnifying-glass" href="/api-reference/data/search-publisher-data">
    POST /ai/data/v1/search
  </Card>

  <Card title="Recommendations" icon="stars" href="/api-reference/data/get-base-item-recommendations">
    POST /ai/v1/data/items/recommendations/base
  </Card>
</CardGroup>

**Invalid Collection — 400**

```json theme={null}
{
  "detail": "Invalid Collection. Please see https://docs.gloo.com/api-guides/search#making-requests for information on providing a valid collection."
}
```

**Missing or Invalid Tenant — 400**

```json theme={null}
{
  "detail": "Unable to search tenant, InvalidTenant, in collection, GlooProd. Please provide a valid tenant. See https://docs.gloo.com/api-guides/search#making-requests for information on providing a valid tenant."
}
```

For multi-tenant collections where tenant is omitted:

```json theme={null}
{
  "detail": "Unable to search multi-tenant collection, GlooProd. Please provide a valid tenant. See https://docs.gloo.com/api-guides/search#making-requests for information on providing a valid tenant."
}
```

**Missing Authorization — 401**

Returned by the gateway when the `Authorization` header is missing.

```json theme={null}
{
  "error": "Missing Authorization",
  "code": "unauthorized_missing_authorization"
}
```

**Invalid Authorization — 403**

Returned by the gateway when the `Authorization` header is present but malformed or the bearer token is invalid.

```json theme={null}
{
  "error": "Forbidden - insufficient permissions",
  "code": "forbidden"
}
```

**Validation Errors — returned as 403**

Empty `query`, empty `collection`, and invalid `limit` values return HTTP `403` rather than `422`. Don't treat these as permission errors — they indicate an invalid request body.

Empty query:

```json theme={null}
{
  "detail": [
    {
      "type": "string_too_short",
      "loc": ["body", "query"],
      "msg": "String should have at least 1 character",
      "input": ""
    }
  ]
}
```

Invalid `limit`:

```json theme={null}
{
  "detail": [
    {
      "type": "greater_than_equal",
      "loc": ["body", "limit"],
      "msg": "Input should be greater than or equal to 1",
      "input": -1
    }
  ]
}
```

<Info>
  Zero results is not an error — it means no content exceeded the certainty threshold. Lower `certainty` toward `0.5` or verify that content has been ingested.
</Info>

***

## Error Handling Best Practices

**Log `error.name` and `error.code`, not just the status** — Status codes tell you the category; the symbolic name and numeric code tell you exactly what went wrong. Log them in your error handler for precise alerting and debugging.

**Use `error.retryable` for Completions retries** — For non-streaming responses, use the HTTP status plus `error.retryable`. For streaming responses, inspect stream error events and use `error.retryable`. Some failures happen inside an HTTP `200` stream after headers have been sent.

**Only retry non-streaming `408`, `429`, and `5xx` responses by default** — `408` provider timeouts are safe to retry with backoff. Other `4xx` errors, except `429`, mean your request has a problem that won't go away on retry.

**Use exponential backoff for retries** — Wait `(2^attempt) + jitter` between retries, up to 5 attempts for non-streaming requests. Live streaming needs much lower ceilings — see [Handling Streaming Failures](/best-practices/completions-streaming-failures) for streaming retry budgets and [Rate Limits](/api-reference/general/limits) for pseudocode.

**Use `detail` to pinpoint validation failures** — For `422` responses, the `detail` array tells you exactly which field failed: `loc` is the field path, `msg` is the reason, and `input` is the value you sent.
