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

# Errors

> API error handling

For errors, BLACKBOX AI returns a JSON response with the following shape:

```typescript TypeScript theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
type ErrorResponse = {
  error: {
    code: number;
    message: string;
    metadata?: Record<string, unknown>;
  };
};
```

The HTTP Response will have the same status code as `error.code`, giving a request error if:

* Your original request is invalid
* Your API key/account is out of credits

Otherwise, the returned HTTP response status will be `200` and any error occurred while the LLM is producing the output will be emitted in the response body or as an SSE data event.
Example code for printing errors:

```typescript TypeScript theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
// Public api users: use https://api.blackbox.ai/chat/completions
const request = await fetch('https://enterprise.blackbox.ai/chat/completions');
console.log(request.status); // Will be an error code unless the model started processing your request
const response = await request.json();
console.error(response.error?.status); // Will be an error code
console.error(response.error?.message);
```

## Error Codes

* `400`: Bad Request (invalid or missing params, CORS)
* `401`: Invalid credentials (OAuth session expired, disabled/invalid API key)
* `402`: Your account or API key has insufficient credits. Add more credits and retry the request.
* `403`: Your chosen model requires moderation and your input was flagged
* `408`: Your request timed out
* `429`: You are being rate limited
* `502`: Your chosen model is down or we received an invalid response from it
* `503`: There is no available model provider that meets your routing requirements

## Moderation Errors

If your input was flagged, the `error.metadata` will contain information about the issue. The shape of the metadata is as follows:

```typescript TypeScript theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
type ModerationErrorMetadata = {
  reasons: string[]; // Why your input was flagged
  flagged_input: string; // The text segment that was flagged, limited to 100 characters. If the flagged input is longer than 100 characters, it will be truncated in the middle and replaced with ...
  provider_name: string; // The name of the provider that requested moderation
  model_slug: string;
};
```

## Provider Errors

If the model provider encounters an error, the `error.metadata` will contain information about the issue. The shape of the metadata is as follows:

```typescript TypeScript theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
type ProviderErrorMetadata = {
  provider_name: string; // The name of the provider that encountered the error
  raw: unknown; // The raw error from the provider
};
```

## Common Errors & How to Avoid Them

These are the errors we see most often in production, what causes them, and how to keep them out of your requests.

### Invalid image data (400)

```json theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
{
  "error": {
    "message": "The image data you provided does not represent a valid image. Please check your input and try again.",
    "type": "invalid_request_error",
    "param": "input",
    "code": "invalid_value"
  }
}
```

This is by far the most common 400 on vision-capable models (e.g. `gpt-5.4`, `gpt-5.5`). It means the bytes behind your `image_url` could not be decoded into a real image. The request never reaches the model — it's rejected up front — so retrying the exact same payload will always fail.

<Tip>
  **Images that work**

  * **Formats:** PNG, JPEG, (non-animated) GIF, and WEBP.
  * **Data URLs:** the prefix must match the real bytes and be complete — `data:image/png;base64,<DATA>`. The base64 string must be the *whole* image, valid, and contain no spaces, newlines, or URL-encoding.
  * **Remote URLs:** must be a direct, publicly reachable `https://` link to the raw image file (not an HTML page, login wall, or redirect), returning an `image/*` content type.
  * **Size:** keep each image under the provider limit (typically **20 MB** decoded) and within reasonable dimensions. Very large images should be downscaled before sending.
</Tip>

<Warning>
  **Images that fail** — these produce the error above:

  * **Truncated or corrupt base64** — the single biggest cause. A string cut off mid-upload (note the \~10 MB request bodies in our logs) decodes to a broken image.
  * **Wrong or missing MIME prefix** — sending `data:image/jpeg;base64,...` when the bytes are actually PNG, or omitting the `data:...;base64,` prefix entirely and sending bare base64.
  * **Whitespace / newlines in the base64** — some encoders wrap base64 at 76 chars. Strip all `\n` and spaces before sending.
  * **Unsupported formats** — SVG, TIFF, HEIC/HEIF, BMP, animated GIF, or PDF pages. Convert to PNG/JPEG first.
  * **Double-encoded or JSON-escaped data** — base64 that has been encoded twice, or had `+`/`/` characters mangled by URL-encoding.
  * **Unreachable remote URLs** — 404s, redirects, signed URLs that have expired, or links that return HTML instead of image bytes.
</Warning>

**How to avoid it**

1. Validate every image **before** sending — decode the base64 and confirm it opens as a real image:
   ```python Python theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
   import base64, io
   from PIL import Image

   def is_valid_image(b64: str) -> bool:
       try:
           Image.open(io.BytesIO(base64.b64decode(b64, validate=True))).verify()
           return True
       except Exception:
           return False
   ```
2. Build the data URL with the **detected** MIME type, not a hard-coded one (use `Image.format` or a `python-magic` sniff).
3. Strip whitespace from base64: `b64 = b64.replace("\n", "").replace(" ", "")`.
4. For remote images, prefer **fetching and inlining** them as base64 yourself so you control the bytes, rather than passing a third-party URL the upstream must download.
5. Downscale large images (e.g. longest edge ≤ 2048 px) to stay under size limits and reduce latency/cost.

### Model produced invalid content (500)

```json theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
{
  "error": {
    "message": "The model produced invalid content. Consider modifying your prompt if you are seeing this error persistently. Please include the request ID ... in your message.",
    "type": "model_error",
    "param": null,
    "code": null
  }
}
```

This is an **upstream provider error** (Azure/OpenAI), not a problem with your request shape — the model began generating but produced output the provider rejected (often during tool-call argument generation or when its content filter trips mid-stream). These can be slow to surface (we've seen \~42 s latency before the 500).

**How to avoid it**

* **Retry with backoff** — this is usually transient. A single retry clears most occurrences, and our router will already failover across regions.
* **Simplify the request if it's persistent** — overly complex tool JSON schemas, deeply nested `required` fields, or ambiguous instructions make the model more likely to emit malformed tool arguments. Flatten schemas and tighten the prompt.
* **Keep the request ID** from the message when escalating to support.
