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

# Error Handling

> Handle SDK errors gracefully

The SDK provides a comprehensive error hierarchy for different failure scenarios.

## Error Hierarchy

```
ComplianceError (base)
├── ValidationError      # Input validation failures
├── APIError             # Server/network errors
│   ├── NotFoundError
│   ├── UnauthorizedError
│   ├── ForbiddenError
│   ├── RateLimitError
│   ├── ServerError
│   ├── NetworkError
│   └── TimeoutError
└── UploadError          # File upload failures
    ├── FileTooLargeError
    ├── UploadTimeoutError
    ├── InvalidFileTypeError
    ├── UploadAbortedError
    └── UploadUrlExpiredError
```

## Basic Error Handling

```typescript theme={null}
import {
  ComplianceError,
  ValidationError,
  NotFoundError,
  UnauthorizedError,
} from "@artu-ai/compliance-sdk";

try {
  const client = await sdk.clients.retrieve("client_123");
} catch (error) {
  if (error instanceof NotFoundError) {
    console.log("Client not found");
  } else if (error instanceof UnauthorizedError) {
    console.log("Invalid API key");
  } else if (error instanceof ValidationError) {
    console.log("Validation errors:", error.issues);
  } else if (error instanceof ComplianceError) {
    console.log("SDK error:", error.message);
  } else {
    throw error; // Re-throw unexpected errors
  }
}
```

## Error Properties

All errors extend `ComplianceError` with these properties:

```typescript theme={null}
interface ComplianceError extends Error {
  message: string; // Human-readable message
  code: string; // Error code (e.g., "NOT_FOUND")
  cause?: Error; // Original error if wrapped
  toJSON(): object; // Serializable representation
}
```

## Validation Errors

Validation errors occur when input data fails schema validation:

```typescript theme={null}
import { ValidationError } from "@artu-ai/compliance-sdk";

try {
  await sdk.clients.create({
    type: "invalid_type",
    name: "",
  });
} catch (error) {
  if (error instanceof ValidationError) {
    console.log("Validation failed:");

    for (const issue of error.issues) {
      console.log(`  ${issue.path.join(".")}: ${issue.message}`);
    }
    // Output:
    //   type: Invalid enum value
    //   name: String must contain at least 1 character
  }
}
```

### Validation Issue Structure

```typescript theme={null}
interface ValidationIssue {
  path: (string | number)[]; // Path to the invalid field
  message: string; // Human-readable error message
  code: string; // Zod error code
}
```

## API Errors

API errors include HTTP status information:

```typescript theme={null}
import { APIError, isAPIError } from "@artu-ai/compliance-sdk";

try {
  await sdk.clients.create({ ... });
} catch (error) {
  if (isAPIError(error)) {
    console.log("Status:", error.statusCode);
    console.log("Code:", error.code);
    console.log("Message:", error.message);
  }
}
```

### Not Found Error

```typescript theme={null}
import { NotFoundError } from "@artu-ai/compliance-sdk";

try {
  await sdk.clients.retrieve("nonexistent_id");
} catch (error) {
  if (error instanceof NotFoundError) {
    console.log("Resource not found");
    console.log("ID:", error.resourceId);
  }
}
```

### Unauthorized Error

```typescript theme={null}
import { UnauthorizedError } from "@artu-ai/compliance-sdk";

try {
  await sdk.clients.list();
} catch (error) {
  if (error instanceof UnauthorizedError) {
    console.log("Authentication failed - check your API key");
  }
}
```

### Forbidden Error

```typescript theme={null}
import { ForbiddenError } from "@artu-ai/compliance-sdk";

try {
  await sdk.alerts.generate({ ... });
} catch (error) {
  if (error instanceof ForbiddenError) {
    console.log("Access denied - insufficient permissions");
  }
}
```

### Rate Limit Error

```typescript theme={null}
import { RateLimitError } from "@artu-ai/compliance-sdk";

try {
  await sdk.clients.list();
} catch (error) {
  if (error instanceof RateLimitError) {
    const retryAfter = error.retryAfter;
    console.log(`Rate limited. Retry after ${retryAfter} seconds`);

    // Wait and retry
    await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));
    await sdk.clients.list();
  }
}
```

### Server Error

```typescript theme={null}
import { ServerError } from "@artu-ai/compliance-sdk";

try {
  await sdk.clients.list();
} catch (error) {
  if (error instanceof ServerError) {
    console.log("Server error - try again later");
    console.log("Request ID:", error.requestId);
  }
}
```

### Network Error

```typescript theme={null}
import { NetworkError } from "@artu-ai/compliance-sdk";

try {
  await sdk.clients.list();
} catch (error) {
  if (error instanceof NetworkError) {
    console.log("Network error - check your connection");
  }
}
```

### Timeout Error

```typescript theme={null}
import { TimeoutError } from "@artu-ai/compliance-sdk";

try {
  await sdk.clients.list();
} catch (error) {
  if (error instanceof TimeoutError) {
    console.log("Request timed out");
  }
}
```

## Upload Errors

Handle file upload failures:

```typescript theme={null}
import {
  UploadError,
  FileTooLargeError,
  InvalidFileTypeError,
  UploadTimeoutError,
  UploadAbortedError,
  UploadUrlExpiredError,
  isUploadError,
} from "@artu-ai/compliance-sdk";

try {
  await sdk.documents.upload({ ... });
} catch (error) {
  if (error instanceof FileTooLargeError) {
    console.log(`File exceeds maximum size of ${error.maxSize} bytes`);
  } else if (error instanceof InvalidFileTypeError) {
    console.log(`Invalid file type: ${error.mimeType}`);
    console.log(`Allowed types: ${error.allowedTypes.join(", ")}`);
  } else if (error instanceof UploadTimeoutError) {
    console.log("Upload timed out");
  } else if (error instanceof UploadAbortedError) {
    console.log("Upload was aborted");
  } else if (error instanceof UploadUrlExpiredError) {
    console.log("Upload URL expired - request a new one");
  } else if (isUploadError(error)) {
    console.log(`Upload failed at stage: ${error.stage}`);
  }
}
```

## Type Guards

Use type guards for cleaner error handling:

```typescript theme={null}
import { isAPIError, isUploadError } from "@artu-ai/compliance-sdk";

try {
  await someOperation();
} catch (error) {
  if (isAPIError(error)) {
    // Handle API errors
  } else if (isUploadError(error)) {
    // Handle upload errors
  }
}
```

## Error Serialization

All errors can be serialized to JSON:

```typescript theme={null}
try {
  await sdk.clients.create({ ... });
} catch (error) {
  if (error instanceof ComplianceError) {
    const json = error.toJSON();
    console.log(JSON.stringify(json, null, 2));
    // {
    //   "name": "ValidationError",
    //   "message": "Invalid input",
    //   "code": "VALIDATION_ERROR",
    //   "issues": [...]
    // }
  }
}
```

## Best Practices

### Catch Specific Errors First

```typescript theme={null}
try {
  await sdk.clients.retrieve(id);
} catch (error) {
  // Catch specific errors first
  if (error instanceof NotFoundError) {
    return null;
  }
  if (error instanceof UnauthorizedError) {
    await refreshToken();
    return sdk.clients.retrieve(id);
  }
  // Then catch base error
  if (error instanceof ComplianceError) {
    logger.error("SDK error", error.toJSON());
  }
  throw error;
}
```

### Retry with Backoff

```typescript theme={null}
async function withRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      if (error instanceof RateLimitError) {
        await new Promise((r) => setTimeout(r, error.retryAfter * 1000));
      } else if (
        error instanceof NetworkError ||
        error instanceof TimeoutError
      ) {
        await new Promise((r) => setTimeout(r, attempt * 1000));
      } else {
        throw error;
      }
    }
  }
  throw new Error("Max retries exceeded");
}

const client = await withRetry(() => sdk.clients.retrieve(id));
```
