# Errors

<!-- Canonical: https://www.atlaso.ai/docs/errors -->

Atlaso's exception hierarchy is pedagogical — error messages list every valid option and point at the right method when applicable. The error *is* the documentation.

## Hierarchy

```text
AtlasoError                              # catch-all
├── ConfigurationError                  # bad construction / call inputs
│   ├── ConfigValidationError           # construction-time
│   └── InputValidationError            # call-time
│       └── MissingContradictsError     # .candidate_parents
├── AuthenticationError                 # HTTP 401 (who you are)
├── TransportError                      # network / HTTP base
│   ├── ConnectError                    # DNS / TCP / TLS — RETRIED
│   ├── RequestTimeoutError             # RETRIED
│   └── APIStatusError                  # .status_code, .response, .request_id
│       ├── PermissionDeniedError       # 401 / 403 — NOT retried
│       ├── NotFoundError               # 404 — NOT retried
│       ├── RateLimitError              # 429 — .retry_after — RETRIED
│       └── ServerError                 # 5xx — RETRIED
├── FieldError                          # gate / invariant base
│   └── DepositRejectedError            # .gate_reason
└── IdempotencyKeyConflict              # .idempotency_key, .existing_id
```

> Atlaso's errors deliberately avoid Python builtin names like `ConnectionError` and `TimeoutError`. Enforced by a CI gate so an upgrade can never silently shadow a builtin in user code.

## Pedagogical messages

```python
from atlaso import InputValidationError

try:
    user.add("hello", polarity="strong")
except InputValidationError as e:
    print(e)
    # polarity must be one of:
    #   "positive"   — claim that X works / is true
    #   "negative"   — claim that X doesn't work / failed
    #   "cautionary" — claim with caveats
    #   "open"       — note or open question
```

## Retry policy

The HTTP client retries transient failures up to `max_retries` times with exponential backoff.

**Retried:**

- `ConnectError` — DNS, TCP, TLS failures
- `RequestTimeoutError`
- `RateLimitError` — respects `Retry-After` header
- `ServerError` — 5xx

**Not retried (would be silently destructive):**

- `PermissionDeniedError` — 401 / 403
- `NotFoundError` — 404
- `AuthenticationError` — wrong API key
- `InputValidationError`, `DepositRejectedError`, `IdempotencyKeyConflict` — caller bugs

## Rich error fields

```python
from atlaso import (
    APIStatusError, RateLimitError,
    DepositRejectedError, IdempotencyKeyConflict, InputValidationError,
)

try:
    user.add(...)
except DepositRejectedError as e:
    print(e.gate_reason)            # human-readable rule trace

try:
    user.add_many(items, ...)
except IdempotencyKeyConflict as e:
    print(e.idempotency_key, "already mapped to", e.existing_id)

try:
    user.contradict(text, contradicts=[], reason="…")
except InputValidationError as e:
    # Memory.contradict() validates non-empty contradicts at call-time.
    print(e)

try:
    ...
except RateLimitError as e:
    sleep(e.retry_after or 1.0)

try:
    ...
except APIStatusError as e:
    print(e.status_code, e.request_id, e.response)
```

`SyncInAsyncWarning` and `FrameworkExtraReservedWarning` subclass `Warning` directly (not `UserWarning`) so a shop that sets `warnings.filterwarnings('error', category=UserWarning)` won't hard-fail on them.

---

<!-- atlaso:doc-trailer -->
**Source:** <https://www.atlaso.ai/docs/errors>  
**Edit on GitHub:** <https://github.com/imashishkh21/atlaso/tree/main/docs/errors.md>  
**Updated:** 2026-05-12
