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

# Error Handling

> SDK error types, retryability, and retry configuration for the LaserSell API.

## `ExitApiError` Kinds

Every SDK exposes an `ExitApiError` (or equivalent) with a `kind` discriminator:

| Kind              | Trigger                                   | Retryable                   |
| ----------------- | ----------------------------------------- | --------------------------- |
| `transport`       | Network failure, DNS error, timeout       | Yes                         |
| `http_status`     | Non 2xx HTTP response                     | Yes if status >= 500 or 429 |
| `envelope_status` | Server returned `{ "status": "error" }`   | No                          |
| `parse`           | Response body could not be parsed as JSON | No                          |

### Checking Retryability

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { ExitApiError } from "@lasersell/lasersell-sdk";

  try {
    const response = await client.buildSellTx(request);
  } catch (error) {
    if (error instanceof ExitApiError) {
      console.log("Kind:", error.kind);
      console.log("Retryable:", error.isRetryable());
      console.log("HTTP status:", error.status);
      console.log("Body:", error.body);
    }
  }
  ```

  ```python Python theme={null}
  from lasersell_sdk.exit_api import ExitApiError

  try:
      response = await client.build_sell_tx(request)
  except ExitApiError as error:
      print("Kind:", error.kind)
      print("Retryable:", error.is_retryable())
      print("HTTP status:", error.status)
      print("Body:", error.body)
  ```

  ```rust Rust theme={null}
  use lasersell_sdk::exit_api::ExitApiError;

  match client.build_sell_tx(&request).await {
      Ok(response) => { /* use response */ }
      Err(error) => {
          eprintln!("Kind: {:?}", error.kind());
          eprintln!("Retryable: {}", error.is_retryable());
      }
  }
  ```

  ```go Go theme={null}
  import lasersell "github.com/lasersell/lasersell-sdk/go"

  resp, err := client.BuildSellTx(ctx, request)
  if err != nil {
      var apiErr *lasersell.ExitAPIError
      if errors.As(err, &apiErr) {
          fmt.Println("Kind:", apiErr.Kind)
          fmt.Println("Retryable:", apiErr.IsRetryable())
          fmt.Println("HTTP status:", apiErr.Status)
      }
  }
  ```
</CodeGroup>

## Built in Retry Behavior

All SDKs include automatic retry with these defaults:

| Setting         | Default Value |
| --------------- | ------------- |
| Max attempts    | 2             |
| Initial backoff | 25 ms         |
| Max backoff     | 25 ms         |
| Jitter          | 25 ms         |
| Connect timeout | 200 ms        |
| Attempt timeout | 900 ms        |

Retries only trigger for errors where `isRetryable()` returns `true` (transport failures, 5xx responses, and 429 rate limits).

### Customizing Retry Policy

<CodeGroup>
  ```typescript TypeScript theme={null}
  const client = ExitApiClient.withOptions("YOUR_API_KEY", {
    attempt_timeout_ms: 2000,
    retry_policy: {
      max_attempts: 3,
      initial_backoff_ms: 50,
      max_backoff_ms: 200,
      jitter_ms: 50,
    },
  });
  ```

  ```python Python theme={null}
  from lasersell_sdk.exit_api import ExitApiClient, ExitApiClientOptions
  from lasersell_sdk.retry import RetryPolicy

  client = ExitApiClient.with_options(
      "YOUR_API_KEY",
      ExitApiClientOptions(
          attempt_timeout_s=2.0,
          retry_policy=RetryPolicy(
              max_attempts=3,
              initial_backoff_ms=50,
              max_backoff_ms=200,
              jitter_ms=50,
          ),
      ),
  )
  ```

  ```rust Rust theme={null}
  use std::time::Duration;
  use lasersell_sdk::exit_api::{ExitApiClient, ExitApiClientOptions};
  use lasersell_sdk::retry::RetryPolicy;
  use secrecy::SecretString;

  let client = ExitApiClient::with_options(
      Some(SecretString::new("YOUR_API_KEY".into())),
      ExitApiClientOptions {
          connect_timeout: Duration::from_millis(200),
          attempt_timeout: Duration::from_millis(2000),
          retry_policy: RetryPolicy {
              max_attempts: 3,
              initial_backoff: Duration::from_millis(50),
              max_backoff: Duration::from_millis(200),
              jitter: Duration::from_millis(50),
          },
      },
  )?;
  ```

  ```go Go theme={null}
  import (
      "time"
      lasersell "github.com/lasersell/lasersell-sdk/go"
  )

  client := lasersell.NewExitAPIClientWithOptions("YOUR_API_KEY", lasersell.ExitAPIClientOptions{
      ConnectTimeout: 200 * time.Millisecond,
      AttemptTimeout: 2000 * time.Millisecond,
      RetryPolicy: lasersell.RetryPolicy{
          MaxAttempts:    3,
          InitialBackoff: 50 * time.Millisecond,
          MaxBackoff:     200 * time.Millisecond,
          Jitter:         50 * time.Millisecond,
      },
  })
  ```
</CodeGroup>
