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

# Error handling

> How to handle errors in the Tinfoil SDKs

## API Errors

Since the Tinfoil SDK wraps the OpenAI client, standard API errors (`AuthenticationError`, `RateLimitError`, etc.) pass through unchanged. The SDK re-exports them so you can import and catch them directly. See the [OpenAI error documentation](https://developers.openai.com/docs/guides/error-codes) for details.

<Accordion defaultOpen title="Example: handling an AuthenticationError">
  <CodeGroup>
    ```typescript JavaScript theme={"dark"}
    import { TinfoilAI, AuthenticationError } from "tinfoil";

    const client = new TinfoilAI({
      apiKey: "tk_invalid_key",
    });

    try {
      await client.chat.completions.create({
        model: "<MODEL_NAME>",
        messages: [{ role: "user", content: "Hello!" }],
      });
    } catch (err) {
      if (err instanceof AuthenticationError) {
        console.error("Invalid API key:", err.status, err.message);
      }
    }
    ```

    ```rust Rust theme={"dark"}
    use tinfoil::async_openai::error::OpenAIError;
    use tinfoil::error::Error;
    use tinfoil::Client;

    let client = Client::new_default_with_api_key("tk_invalid_key").await?;

    match client.chat().create(request).await {
        Err(OpenAIError::ApiError(api)) if api.code.as_deref() == Some("invalid_api_key") => {
            eprintln!("Invalid API key: {}", api.message);
        }
        Err(other) => return Err(Error::from(other).into()),
        Ok(_) => {}
    }
    ```
  </CodeGroup>
</Accordion>

## Client Errors

The SDK verifies attestations, pins certificates, and encrypts payloads before any data leaves your machine. It retries transient failures automatically, but errors that persist will surface to your code as one of two typed errors.

```
TinfoilError (base)
├── ConfigurationError  — Client misconfigured
└── AttestationError    — Attestation verification failed
```

All errors extend `TinfoilError`, which extends the native `Error` class. Each error includes a `message` string and an optional `cause` property containing the underlying error.

| Error                | Cause                           | What to do                                                       |
| -------------------- | ------------------------------- | ---------------------------------------------------------------- |
| `ConfigurationError` | Bad or missing client options   | Fix your code. Retrying will not help.                           |
| `AttestationError`   | Attestation verification failed | Retry. If it persists, it may indicate a genuine security issue. |

In practice, you typically only need to distinguish `ConfigurationError` (a bug in your code) from transient errors:

<CodeGroup>
  ```typescript JavaScript theme={"dark"}
  import { TinfoilAI, ConfigurationError, TinfoilError } from "tinfoil";

  try {
    const completion = await client.chat.completions.create({
      model: "<MODEL_NAME>",
      messages: [{ role: "user", content: "Hello!" }],
    });
  } catch (err) {
    if (err instanceof ConfigurationError) {
      // Fix your config and create a new client
    } else if (err instanceof TinfoilError) {
      // Transient or security error — you can retry or surface to the user
      console.error(err.message, err.cause); // cause has the underlying error
    }
  }
  ```

  ```rust Rust theme={"dark"}
  use tinfoil::error::Error;
  use tinfoil::Client;

  match client.chat().create(request).await.map_err(Error::from) {
      Ok(completion) => { /* use completion */ }
      Err(err) if err.is_configuration() => {
          // Fix your config and create a new client
      }
      Err(err) if err.is_attestation() => {
          // Security-relevant: do not retry blindly
          eprintln!("attestation failure: {}", err);
      }
      Err(err) if err.is_retryable() => {
          // Transient — fetch error or 5xx/429 from the upstream API
          eprintln!("transient error, retrying: {}", err);
      }
      Err(err) => return Err(err.into()),
  }
  ```
</CodeGroup>
