---
updatedAt: 2026-05-05T11:55:48.000Z
agentTools:
  projectIndex: https://developers.docdigitizer.com/llms.txt
---

# Error Handling

# Error Handling

Understanding and handling errors in DocDigitizer APIs.

## Error Response Format

All errors follow this structure:

```json
{
  "stateText": "ERROR",
  "traceId": "XYZ7890",
  "timers": {
    "DocIngester_Total": 45.23
  },
  "messages": [
    "Human-readable error message"
  ]
}
```

### Response Fields

| Field       | Description                            |
| ----------- | -------------------------------------- |
| `stateText` | Always `"ERROR"` for error responses   |
| `traceId`   | Unique identifier - provide to support |
| `timers`    | Processing time until error occurred   |
| `messages`  | Array of error descriptions            |

## HTTP Status Codes

### 400 Bad Request

Invalid request parameters or file format.

**Common causes:**

* File is not a valid PDF
* Missing required parameters
* Invalid format

**Example:**

```json
{
  "StateText": "ERROR",
  "TraceId": "BAD1234",
  "Messages": ["File must be a PDF document"]
}
```

**Resolution:**

* Verify the file is a valid PDF
* Check all required parameters are provided

### 401 Unauthorized

Authentication failed.

**Common causes:**

* Missing `X-API-Key` header
* Invalid or revoked API key
* Expired API key

**Example:**

```json
{
  "StateText": "ERROR",
  "TraceId": "UNA1234",
  "Messages": ["Invalid or missing API key"]
}
```

**Resolution:**

* Verify the `X-API-Key` header is included
* Check the API key is correct and active
* Generate a new key if needed

### 403 Forbidden

Authorization failed - key is valid but lacks permission.

**Common causes:**

* Subscription doesn't include this feature
* API key doesn't have required scope
* Account suspended

**Resolution:**

* Check your subscription plan
* Verify the API key's permissions
* Contact support if your account may be suspended

### 500 Internal Server Error

Server-side processing error.

**Common causes:**

* Document processing failed
* Downstream service error
* Temporary system issue

**Example:**

```json
{
  "StateText": "ERROR",
  "TraceId": "ERR9876",
  "Messages": [
    "DocWorker returned error: 500",
    "Processing failed. Check server logs for details."
  ]
}
```

**Resolution:**

* Retry the request after a short delay
* If persistent, contact support with the TraceId

### 503 Service Unavailable

Service temporarily unavailable.

**Common causes:**

* System maintenance
* Downstream service unreachable
* Resource exhaustion

**Example:**

```json
{
  "StateText": "ERROR",
  "TraceId": "SVC1234",
  "Messages": ["Cannot connect to DocWorker: Connection refused"]
}
```

**Resolution:**

* Wait and retry with exponential backoff
* Check system status if available
* Contact support if issue persists

### 504 Gateway Timeout

Request took too long to process.

**Common causes:**

* Very large document
* Complex document structure
* System under heavy load

**Example:**

```json
{
  "StateText": "ERROR",
  "TraceId": "TMO1234",
  "Messages": ["DocWorker request timed out"]
}
```

**Resolution:**

* For large documents, consider splitting
* Retry during off-peak hours
* Contact support for large document processing

## Error Handling Best Practices

### 1. Always Check stateText

```python
result = response.json()

if result["stateText"] == "ERROR":
    handle_error(result)
else:
    process_success(result)
```

### 2. Log the traceId

Always log the traceId for debugging:

```python
if result["stateText"] == "ERROR":
    logger.error(f"API Error - TraceId: {result['traceId']}, Messages: {result['messages']}")
```

### 3. Implement Retry Logic

For transient errors (5xx), implement retry with backoff:

```python
import time
import random

def process_with_retry(file_path, max_retries=3):
    for attempt in range(max_retries):
        result = call_api(file_path)

        if result["stateText"] != "ERROR":
            return result

        # Check if error is retryable
        if response.status_code < 500:
            raise NonRetryableError(result["messages"])

        # Exponential backoff with jitter
        delay = (2 ** attempt) + random.uniform(0, 1)
        time.sleep(delay)

    raise MaxRetriesExceeded()
```

### 4. Handle Specific Error Types

```python
def handle_error(result, status_code):
    trace_id = result.get("traceId", "unknown")
    messages = result.get("messages", ["Unknown error"])

    if status_code == 400:
        # Client error - fix the request
        raise ValidationError(messages, trace_id)

    elif status_code == 401:
        # Auth error - check API key
        raise AuthenticationError(messages, trace_id)

    elif status_code == 403:
        # Permission error - check subscription
        raise PermissionError(messages, trace_id)

    elif status_code in [500, 502, 503, 504]:
        # Server error - retry
        raise RetryableError(messages, trace_id)

    else:
        raise UnknownError(messages, trace_id)
```

## Common Errors and Solutions

| Error Message                            | Cause                        | Solution                                |
| ---------------------------------------- | ---------------------------- | --------------------------------------- |
| "File must be a PDF document"            | Wrong file type or extension | Ensure file is PDF with .pdf extension  |
| "Invalid or missing 'id' parameter"      | Missing document ID          | Provide a valid UUID for the `id` field |
| "File does not appear to be a valid PDF" | Corrupted or invalid PDF     | Verify PDF opens correctly locally      |
| "No files submitted"                     | Missing file in request      | Check multipart form data includes file |
| "One file at a time"                     | Multiple files sent          | Send one PDF per request                |

<br />