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

# Errors

> Error types, status codes, and retry behavior

```typescript theme={null}
import { NotFoundError, RateLimitError } from '@airstore/sdk'

try {
  await airstore.workspaces.retrieve('ws_nonexistent')
} catch (err) {
  if (err instanceof NotFoundError) {
    console.log('Workspace not found')
  }
}
```

The SDK throws typed errors for every failure mode. Use `instanceof` checks to handle specific cases.

## Error hierarchy

| Class                       | HTTP Status | When it's thrown                                                                                                                    |
| --------------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `AirstoreError`             | --          | Base class for all SDK errors. Also thrown for configuration issues (missing API key) and client-side problems (cancelled request). |
| `APIError`                  | varies      | Base class for all API errors. Includes `status`, `headers`, and `requestId`.                                                       |
| `AuthenticationError`       | 401         | Invalid or missing API key.                                                                                                         |
| `PermissionDeniedError`     | 403         | Token doesn't have permission for this operation.                                                                                   |
| `NotFoundError`             | 404         | Resource doesn't exist, or token doesn't have access to it.                                                                         |
| `ConflictError`             | 409         | Conflicting operation (e.g., duplicate name).                                                                                       |
| `UnprocessableEntityError`  | 422         | Request validation failed.                                                                                                          |
| `RateLimitError`            | 429         | Too many requests. The client auto-retries these.                                                                                   |
| `InternalServerError`       | 5xx         | Server error. The client auto-retries these.                                                                                        |
| `APIConnectionError`        | --          | Network-level failure (DNS, TCP, TLS).                                                                                              |
| `APIConnectionTimeoutError` | --          | Request timed out.                                                                                                                  |

## Error properties

All `APIError` subclasses include:

```typescript theme={null}
try {
  await airstore.workspaces.retrieve('ws_bad')
} catch (err) {
  if (err instanceof APIError) {
    console.log(err.status)    // 404
    console.log(err.message)   // "workspace not found"
    console.log(err.requestId) // "req_abc123" (if available)
    console.log(err.headers)   // Response Headers object
  }
}
```

| Property    | Type                  | Description                                              |
| ----------- | --------------------- | -------------------------------------------------------- |
| `status`    | `number`              | HTTP status code                                         |
| `message`   | `string`              | Error message from the API                               |
| `headers`   | `Headers`             | Response headers                                         |
| `requestId` | `string \| undefined` | `x-request-id` header value, useful for support requests |

## Retry behavior

The client automatically retries requests that fail with these status codes: `408`, `409`, `429`, `500`, `502`, `503`, `504`.

Retries use exponential backoff starting at 500ms, capped at 8 seconds, with random jitter. If the server sends a `Retry-After` header, the client respects that timing instead.

By default, the client retries up to 2 times (3 total attempts). You can configure this:

```typescript theme={null}
// Client-level
const airstore = new Airstore({ maxRetries: 5 })

// Per-request
await airstore.workspaces.list({ maxRetries: 0 }) // no retries
```

If all retries are exhausted, the SDK throws the last error it received.

## Handling specific errors

```typescript theme={null}
import {
  AuthenticationError,
  NotFoundError,
  RateLimitError,
  APIConnectionError,
} from '@airstore/sdk'

try {
  const ws = await airstore.workspaces.retrieve('ws_abc123')
} catch (err) {
  if (err instanceof AuthenticationError) {
    // Bad API key -- check AIRSTORE_API_KEY
  } else if (err instanceof NotFoundError) {
    // Workspace doesn't exist
  } else if (err instanceof RateLimitError) {
    // Shouldn't normally hit this (auto-retried), but possible if retries exhausted
  } else if (err instanceof APIConnectionError) {
    // Network issue -- DNS, firewall, etc.
  } else {
    throw err // unexpected
  }
}
```

## Cancellation

Pass an `AbortSignal` to cancel a request:

```typescript theme={null}
const controller = new AbortController()

// Cancel after 5 seconds
setTimeout(() => controller.abort(), 5_000)

try {
  await airstore.fs.read('ws_abc123', { path: '/large-file' }, {
    signal: controller.signal,
  })
} catch (err) {
  if (err instanceof AirstoreError && err.message === 'Request was cancelled') {
    console.log('Cancelled')
  }
}
```
