# Error Codes

Complete list of error codes for the SnackPrompt AI Engine API.

### Overview

The API returns errors in the following format:

```json
{
  "detail": "Message describing the error"
}
```

### HTTP Codes

| Code | Name                  | Description                            |
| ---- | --------------------- | -------------------------------------- |
| 200  | OK                    | Successful request                     |
| 202  | Accepted              | Request accepted for processing        |
| 400  | Bad Request           | Validation error or invalid parameters |
| 401  | Unauthorized          | Not authenticated                      |
| 403  | Forbidden             | No permission to access resource       |
| 404  | Not Found             | Resource not found                     |
| 422  | Unprocessable Entity  | Invalid data                           |
| 429  | Too Many Requests     | Rate limit exceeded                    |
| 500  | Internal Server Error | Internal server error                  |
| 503  | Service Unavailable   | Service temporarily unavailable        |

***

### Common Errors

#### 400 - tenant\_id Required

**Response:**

```json
{
  "detail": "tenant_id is required in filters"
}
```

**Cause:** The `tenant_id` was not included in the `filters` object.

**Solution:** Add `tenant_id` to filters:

```json
{
  "query": "your search",
  "filters": {
    "tenant_id": "your-tenant-id"
  }
}
```

***

#### 400 - Query Required

**Response:**

```json
{
  "detail": "query is required"
}
```

**Cause:** The `query` field was not provided in a search or chat request.

**Solution:** Add the `query` field:

```json
{
  "query": "your question here",
  "filters": {
    "tenant_id": "..."
  }
}
```

***

#### 400 - Invalid Filters

**Response:**

```json
{
  "detail": "Invalid filter: unknown_field"
}
```

**Cause:** An unknown filter was provided.

**Solution:** Use only valid filters. See Filter Reference.

***

#### 404 - Elemental Not Found

**Response:**

```json
{
  "detail": "Elemental not found: elem-123"
}
```

**Cause:** The provided `elemental_id` doesn't exist or hasn't been ingested.

**Solution:**

1. Check if the ID is correct
2. Check if the elemental was ingested
3. Wait for ingestion to complete (asynchronous process)

***

#### 422 - Invalid Data

**Response:**

```json
{
  "detail": [
    {
      "loc": ["body", "filters", "limit"],
      "msg": "value is not a valid integer",
      "type": "type_error.integer"
    }
  ]
}
```

**Cause:** A field was provided with the wrong type.

**Solution:** Check data types. See Data Models.

***

#### 429 - Rate Limit

**Response:**

```json
{
  "detail": "Rate limit exceeded. Try again in 60 seconds."
}
```

**Cause:** Too many requests in a short period.

**Solution:**

1. Wait the indicated time
2. Implement retry with exponential backoff
3. Consider upgrading your plan for more requests

**Response headers:**

```
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1699999999
```

***

#### 500 - Internal Error

**Response:**

```json
{
  "detail": "Internal server error"
}
```

**Cause:** Unexpected server error.

**Solution:**

1. Try again in a few seconds
2. If it persists, contact support
3. Include the `trace_id` if available

***

#### 503 - Service Unavailable

**Response:**

```json
{
  "detail": "Service temporarily unavailable"
}
```

**Cause:** The service or a dependency is unavailable.

**Solution:**

1. Wait a few minutes
2. Check status at `/health/detailed`
3. Contact support if it persists

***

### Streaming Errors

#### Error During Streaming

During streaming chat, errors are sent as SSE events:

```
data: {"event":"error","data":{"message":"Error generating response"}}
```

**Solution:** Handle the `error` event in your client:

```javascript
eventSource.addEventListener('message', (event) => {
  const data = JSON.parse(event.data);
  if (data.event === 'error') {
    console.error('Stream error:', data.data.message);
  }
});
```

***

### Recommended Error Handling

#### JavaScript/TypeScript

```typescript
async function searchKnowledgeBase(query: string, tenantId: string) {
  try {
    const response = await fetch('https://api-integrations.snackprompt.com/v1/kb/search', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        query,
        filters: { tenant_id: tenantId }
      })
    });

    if (!response.ok) {
      const error = await response.json();

      switch (response.status) {
        case 400:
          throw new Error(`Validation error: ${error.detail}`);
        case 404:
          throw new Error(`Not found: ${error.detail}`);
        case 429:
          throw new Error('Rate limit exceeded. Please wait.');
        default:
          throw new Error(`API error: ${error.detail}`);
      }
    }

    return await response.json();
  } catch (error) {
    console.error('Search failed:', error);
    throw error;
  }
}
```

#### Python

```python
import requests

def search_knowledge_base(query: str, tenant_id: str):
    try:
        response = requests.post(
            'https://api-integrations.snackprompt.com/v1/kb/search',
            json={
                'query': query,
                'filters': {'tenant_id': tenant_id}
            }
        )
        response.raise_for_status()
        return response.json()

    except requests.exceptions.HTTPError as e:
        if e.response.status_code == 400:
            raise ValueError(f"Validation error: {e.response.json()['detail']}")
        elif e.response.status_code == 429:
            raise Exception("Rate limit exceeded")
        else:
            raise Exception(f"API error: {e.response.json()['detail']}")
```

***

### Retry with Exponential Backoff

For 429 and 5xx errors, implement retry with backoff:

```python
import time
import random

def retry_with_backoff(func, max_retries=3):
    for attempt in range(max_retries):
        try:
            return func()
        except Exception as e:
            if attempt == max_retries - 1:
                raise

            wait_time = (2 ** attempt) + random.uniform(0, 1)
            print(f"Retry {attempt + 1}/{max_retries} in {wait_time:.1f}s")
            time.sleep(wait_time)
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.snackprompt.com/bring-your-data-into-ai/reference/error-codes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
