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

# Error Handling

> Handle API errors with typed error classes in the Triqai SDK

All API errors are thrown as `TriqaiError` instances. Common HTTP statuses are mapped to typed subclasses so you can handle specific failure modes precisely.

## Basic Usage

```typescript theme={null}
import Triqai, {
  TriqaiError,
  AuthenticationError,
  ValidationError,
  RateLimitError,
  InsufficientCreditsError,
  NotFoundError,
} from "triqai";

try {
  await triqai.transactions.enrich({
    title: "",
    country: "US",
    type: "expense",
  });
} catch (err) {
  if (err instanceof ValidationError) {
    console.log("Field errors:", err.fieldErrors);
    // { title: ["Title cannot be empty"] }
  } else if (err instanceof RateLimitError) {
    console.log("Retry after:", err.rateLimitInfo.retryAfter, "seconds");
  } else if (err instanceof AuthenticationError) {
    console.log("Check your API key");
  } else if (err instanceof InsufficientCreditsError) {
    console.log("Top up credits at https://triqai.com/dashboard");
  } else if (err instanceof NotFoundError) {
    console.log("Resource not found");
  } else if (err instanceof TriqaiError) {
    console.log(`API error ${err.statusCode}: ${err.message} [${err.code}]`);
    console.log("Request ID:", err.requestId);
  }
}
```

## Error Classes

Every error extends `TriqaiError` and includes `statusCode`, `message`, `code`, and `requestId` properties.

| Class                      | Status | When                                             |
| -------------------------- | ------ | ------------------------------------------------ |
| `AuthenticationError`      | 401    | Invalid or missing API key                       |
| `InsufficientCreditsError` | 402    | No credits remaining                             |
| `AuthorizationError`       | 403    | Key valid but not authorized for this resource   |
| `NotFoundError`            | 404    | Resource does not exist                          |
| `DuplicateRequestError`    | 409    | Idempotency key reused with different parameters |
| `ValidationError`          | 422    | Request body validation failed                   |
| `RateLimitError`           | 429    | Rate limit exceeded                              |
| `ClientDisconnectedError`  | 499    | Client disconnected before response completed    |
| `InternalServerError`      | 500    | Server error (retried automatically)             |
| `ServiceUnavailableError`  | 503    | Service temporarily down (retried automatically) |
| `GatewayTimeoutError`      | 504    | Upstream timeout                                 |
| `ConnectionError`          | —      | Network or DNS failure                           |
| `TimeoutError`             | —      | Request exceeded configured timeout              |

## Validation Errors

`ValidationError` includes a `fieldErrors` property with per-field error messages:

```typescript theme={null}
try {
  await triqai.transactions.enrich({
    title: "",
    country: "INVALID",
    type: "expense",
  });
} catch (err) {
  if (err instanceof ValidationError) {
    console.log(err.fieldErrors);
    // { title: ["Title cannot be empty"], country: ["Invalid country code"] }
  }
}
```

## Rate Limit Errors

`RateLimitError` includes a `rateLimitInfo` property with retry timing:

```typescript theme={null}
try {
  await triqai.transactions.enrich({ ... });
} catch (err) {
  if (err instanceof RateLimitError) {
    console.log(err.rateLimitInfo.retryAfter);    // seconds until reset
    console.log(err.rateLimitInfo.limit);          // max tokens
    console.log(err.rateLimitInfo.remaining);      // tokens left
  }
}
```
