# Errors, events, and run states

Catch `MakraError` for any SDK exception. Catch narrower classes when the application has a specific recovery action.

## Exception hierarchy

| Exception | Condition | Useful fields |
| --- | --- | --- |
| `MakraAPIError` | Any HTTP API error | `status_code`, `body`, `method`, `path`, `code`, `request_id` |
| `MakraAuthenticationError` | Missing, invalid, revoked, or expired credential | API error fields |
| `MakraPermissionError` | Valid credential lacks permission | API error fields |
| `MakraNotFoundError` | Run or result absent or inaccessible | API error fields |
| `MakraInvalidRequestError` | Contract or URL admission rejection | `field`, `reason`, `index` |
| `MakraInsufficientCreditsError` | Balance cannot cover admission | `required_credits`, `available_credits` |
| `MakraRateLimitError` | Request or active-run limit | `retry_after`, `concurrency` |
| `MakraServerError` | API or upstream service failure | API error fields |
| `MakraConnectionError` | Transport could not reach API | `method`, `path` |
| `MakraTimeoutError` | Request or stream timeout | Connection error fields |
| `MakraStreamError` | Stream ended before terminal recovery | `run_id` |
| `MakraResultError` | Stored result redirect or download contract failed | `run_id`, sanitized `location` |
| `MakraRunFailedError` | Waited run ended outside `completed` | `run_id`, `state`, `run` |

Local argument validation raises `ValueError`, not `MakraError`.

```python
from makra import Makra, MakraAPIError, MakraConnectionError

try:
    with Makra() as client:
        client.extract(
            ["https://shop.example/products/atlas-lamp"],
            {"price": "The current selling price"},
        )
except MakraAPIError as error:
    print(error.status_code, error.code, error.request_id)
    raise
except MakraConnectionError as error:
    print(error.method, error.path)
    raise
```

## Run states

Non-terminal states are `queued`, `running`, and `cancel_requested`. Terminal states are `completed`, `failed`, `cancelled`, and `budget_exhausted`.

`run_is_terminal(run)` checks state membership. `run_succeeded(run)` requires `completed` and rejects an explicit domain `success` value of false.

## Public event types

The event stream can emit run started, heartbeat, step started, step progress, step completed, partial result, diagnostic, run completed, run failed, run cancelled, and run budget exhausted events. Compare `event.type` with constants on `EventTypes`.

`event.detail_type` exposes finer internal progress names through `StreamDetailTypes`, including stage, activity, message, result, diagnostic, and title events. Treat unknown future detail types as observable events, not fatal parser errors.

## Structured API error codes

Known gateway codes include insufficient credits, too many concurrent runs, idempotency key reuse, invalid workflow URL, invalid request contract, streaming unavailable, run not terminal, result not available, result temporarily unavailable, and not found.

Branch on exception class first. Use `error.code` when two conditions within one HTTP status need different recovery.

Return to [What Makra is](/markdown/makra-sdk/v0.0.3-beta/foundations/what-makra-is).
