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

# Exception reference

> Every exception the SDK raises, what triggers it, and what context it carries.

All SDK exceptions are importable from the top-level package:

```python theme={null}
from minerva import (
    MinervaError,                # base
    MinervaConfigError,
    MinervaValidationError,
    MinervaAuthError,
    MinervaRateLimitError,
    MinervaAPIError,
    MinervaWIPWarning,
)
```

## `MinervaError`

Base for everything the SDK raises. Catch this to handle "any SDK failure"
without caring about the specific cause.

## `MinervaConfigError(MinervaError)`

Misconfiguration — usually surfaces at first call, not at `Minerva(...)`
construction. Fix is always: pass the missing value via constructor arg or
env var.

## `MinervaValidationError(MinervaError)`

Boundary validation failed — input never left the process.

```python theme={null}
try:
    mc.api.enrich([])    # 0 records — must be ≥ 1
except MinervaValidationError as e:
    print(e)
```

Raised by the request models (pydantic) when input shape is wrong, by
`mc.api.call()` when `path` is empty / doesn't start with `/`, and by every
method's preflight when record counts / required fields fail.

## `MinervaAuthError(MinervaError)`

401 / 403 from the server, or no usable credential at all. Common causes:

* API key missing — `MINERVA_API_KEY` not set and no `api_key=` passed
* API key invalid or revoked
* Caller not entitled to the endpoint hit (returned by the server-side authorizer)

## `MinervaRateLimitError(MinervaError)`

HTTP 429.

**Attributes:**

* `.retry_after` — seconds (float) if the server supplied a `Retry-After` header

```python theme={null}
try:
    mc.api.enrich(batch)
except MinervaRateLimitError as e:
    time.sleep(e.retry_after or 1)
```

## `MinervaAPIError(MinervaError)`

Any other non-2xx response from the server.

**Attributes:**

* `.status_code` — HTTP status (int)
* `.api_request_id` — server's trace ID — **quote this when reporting issues**
* `.body` — parsed response body if available

```python theme={null}
try:
    mc.api.enrich(records)
except MinervaAPIError as e:
    log.error("Minerva %s: %s", e.status_code, e.api_request_id)
```

**HTTP 402 — Minerva credits exhausted.** The `.body` dict contains `records_remaining`
(an estimate of how many records you have left based on your credit balance) and
`records_requested` (the batch size that was rejected):

```python theme={null}
except MinervaAPIError as e:
    if e.status_code == 402:
        body = e.body or {}
        print(f"~{body.get('records_remaining')} records remaining, "
              f"requested: {body.get('records_requested')}")
```

## `MinervaWIPWarning` *(warning, not an error)*

Emitted via `warnings.warn` when you exercise an SDK feature that ships for
forward-compat but isn't fully GA. The feature still runs; the warning just
signals "this isn't GA, behaviour may change."

Inherits from `UserWarning`, so the standard `warnings` machinery applies:

```python theme={null}
import warnings
from minerva import MinervaWIPWarning

# Suppress wholesale:
warnings.filterwarnings("ignore", category=MinervaWIPWarning)

# Or turn it into an error to catch every use during development:
warnings.filterwarnings("error", category=MinervaWIPWarning)
```

No methods currently emit it — it's exported infrastructure for future use.
