> For the complete documentation index, see [llms.txt](https://docs.theacompute.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.theacompute.com/api-reference/errors.md).

# Errors

When something fails, I tell you with a conventional HTTP status code. I also send a JSON body with every failed request, pairing a stable, machine-readable `code` with a `message` meant for humans.

***

## How I shape an error

```json
{
  "error": {
    "code": "insufficient_credits",
    "message": "Your credit balance (4 credits) is insufficient for the Standard tier (8 credits required).",
    "type": "payment_error",
    "param": null,
    "docs": "https://docs.theacompute.com/api-reference/errors#insufficient_credits"
  }
}
```

| Field     | What I put in it                                                |
| --------- | --------------------------------------------------------------- |
| `code`    | A stable identifier. This is the one to branch your code on     |
| `message` | A plain-language explanation of what went wrong                 |
| `type`    | The broad category I file the error under                       |
| `param`   | The request parameter that caused the failure, if there was one |
| `docs`    | A link straight to the matching error on this page              |

***

## The HTTP status codes I use

| Status | Category            | When I send it                                                                                           |
| ------ | ------------------- | -------------------------------------------------------------------------------------------------------- |
| `400`  | Bad request         | I couldn't parse the body, a required field is missing, or a value is invalid                            |
| `401`  | Authentication      | Your API key is missing, or I don't recognize it                                                         |
| `402`  | Payment             | Your wallet doesn't have enough units                                                                    |
| `403`  | Forbidden           | Your key is suspended, or I don't allow that operation                                                   |
| `404`  | Not found           | I can't find a job, model, or webhook with that identifier                                               |
| `409`  | Conflict            | The resource already exists, or its state clashes with what you asked for                                |
| `422`  | Unprocessable       | Your request is well-formed but breaks a semantic rule                                                   |
| `429`  | Too many requests   | You ran into my per-IP burst limit on the API layer itself. This has nothing to do with network capacity |
| `500`  | Server error        | Something broke on my side. Trying again usually works                                                   |
| `503`  | Service unavailable | No worker is hosting the model you asked for at the moment                                               |
| `504`  | Gateway timeout     | Your job timed out and I returned your units                                                             |

***

## Every error code I return

### `invalid_api_key`

I've never seen the key you sent, or it has been revoked.

**Status:** 401\
**What to do:** Generate a new key in Settings.

***

### `missing_api_key`

Your request reached me without an `Authorization` header.

**Status:** 401\
**What to do:** Include `Authorization: Bearer thea_live_your_key_here` on each request.

***

### `key_suspended`

I've suspended this key. I do that when an account is flagged for abuse.

**Status:** 403\
**What to do:** Write to <contact@theacompute.com>.

***

### `insufficient_credits`

The wallet tied to this key doesn't hold enough units for the tier you asked for. My API calls units credits, which is why this code and its fields say credits.

**Status:** 402\
**What to do:** Top up in Settings with "Add more units", or choose a model in a cheaper tier.

```json
{
  "error": {
    "code": "insufficient_credits",
    "message": "Your credit balance (4 credits) is insufficient for the Standard tier (8 credits required).",
    "type": "payment_error",
    "details": {
      "credits_remaining": 4,
      "credits_required": 8,
      "tier": "standard"
    }
  }
}
```

***

### `model_not_found`

I don't know any model ID that matches the `model` field in your request.

**Status:** 400\
**What to do:** Call `GET /v1/models` and choose an ID from what I return.

***

### `no_workers_available`

Not a single worker is hosting the model you asked for at the moment. It's temporary, and it clears up as workers come online.

**Status:** 503\
**What to do:** Wait for the `retry_after` interval and try again, or use a different model.

```json
{
  "error": {
    "code": "no_workers_available",
    "message": "No workers are currently available for llama-3.3-70b. Try again in approximately 30 seconds.",
    "type": "capacity_error",
    "details": {
      "model": "llama-3.3-70b",
      "retry_after": 30
    }
  }
}
```

***

### `job_timeout`

My 120-second window ran out before any worker finished the job. I returned the escrowed units automatically, and the `refund_tx` in the details is the on-chain receipt for that refund.

**Status:** 504\
**What to do:** Send the request again. You can spend the refunded units immediately. If one model keeps timing out, its worker pool is thin.

```json
{
  "error": {
    "code": "job_timeout",
    "message": "The inference job timed out after 120 seconds. Your credits have been refunded.",
    "type": "timeout_error",
    "details": {
      "job_id": "job_8fx2kp3m9qrstvwxyz",
      "credits_refunded": 8,
      "refund_tx": "0x5e08c3b71a94f2d6580b1ce9f43a07d218e6c5049fb3a827d15e90cb46281f7a"
    }
  }
}
```

***

### `invalid_request`

I couldn't parse the body, or it's missing a required field.

**Status:** 400\
**What to do:** Look at the `param` field first. I use it to name the field that caused the problem.

***

### `context_length_exceeded`

All the messages in your request add up to more than the chosen model's context window can fit.

**Status:** 400\
**What to do:** Shorten the conversation, or switch to a model with a larger context. I list each model's limit in the `context_window` field of `GET /v1/models`.

***

### `dispute_window_expired`

Your dispute reached me after the 60-second window had closed.

**Status:** 422\
**What to do:** There's nothing you can do here. I only accept a dispute within 60 seconds of the final output token, and I can't extend that window.

***

## How to retry without trouble

Go ahead and retry any 5xx, plus `no_workers_available` (503). Every other error points to a problem with the request itself, so sending me the same payload again will fail in the same way.

Here's the retry strategy I recommend:

```python
import time
import httpx

def call_with_retry(client, payload, max_retries=3):
    for attempt in range(max_retries):
        response = client.post("/v1/chat/completions", json=payload)
        
        if response.status_code == 200:
            return response
        
        error = response.json().get("error", {})
        code = error.get("code")
        
        if response.status_code == 503 and code == "no_workers_available":
            retry_after = error.get("details", {}).get("retry_after", 10)
            time.sleep(retry_after)
            continue
        
        if response.status_code >= 500:
            time.sleep(2 ** attempt)
            continue
        
        # Don't retry my 4xx responses; surface them instead
        response.raise_for_status()
    
    raise Exception(f"Request failed after {max_retries} attempts")
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://docs.theacompute.com/api-reference/errors.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
