# Errors and recovery

Handle login, spending, configuration, and provider failures appropriately.

Catch Enlitt errors around the model operation. Specific classes are exported
from `@enlitt/sdk/core`, with compatibility exports from `@enlitt/sdk/server`.
Use the stable `code` for diagnosis, and show users a message they can act on.

## User actions

| Class                             | Code                                                      | Action                                                                                                         |
| --------------------------------- | --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `EnlittLoginRequiredError`        | `personal_login_required`                                 | Start your application's Enlitt login flow again.                                                              |
| `EnlittLimitExceededError`        | `spending_limit_exceeded`                                 | Explain the rule in `limitRule`; offer the supplied `authorizeUrl` when available.                             |
| `EnlittInsufficientCreditsError`  | `premium_balance_exhausted`, `standard_balance_exhausted` | Offer the supplied `authorizeUrl` to manage credits. A premium error may include `admissibleMaxChargeNanoUsd`. |
| `EnlittSubscriptionInactiveError` | `subscription_inactive`                                   | Ask the user to review their account. Investigate repeated occurrences: users normally retain a free plan.     |

Login errors direct users to your login route. The four spending/credit codes
`spending_limit_exceeded`, `premium_balance_exhausted`,
`standard_balance_exhausted`, and `subscription_inactive` may carry
`authorizeUrl`. It is optional; do not assume every refusal includes a link.

## Integration problems

| Class                       | Code                       | Check on your server                                                                  |
| --------------------------- | -------------------------- | ------------------------------------------------------------------------------------- |
| `EnlittConfigurationError`  | `configuration_invalid`    | Server-only imports, secret, HTTPS base URL, session middleware, and pricing options. |
| `EnlittAuthenticationError` | `invalid_api_key`          | Key validity and revocation status.                                                   |
| `EnlittAuthorizationError`  | `insufficient_permissions` | Key type and application binding.                                                     |

Keep configuration and authentication details in your business logs. Show a
generic service error to the user. Never log a secret or session token.

## Example recovery

This server-side helper returns a simple result your UI can render:

```ts
import {
  EnlittLoginRequiredError,
  EnlittLimitExceededError,
  EnlittInsufficientCreditsError,
  EnlittSubscriptionInactiveError
} from "@enlitt/sdk/core";

export async function runForUser<T>(run: () => Promise<T>) {
  try {
    return { ok: true as const, value: await run() };
  } catch (error) {
    if (error instanceof EnlittLoginRequiredError) {
      return {
        ok: false as const,
        message: "Sign in with Enlitt to continue.",
        href: "/auth/enlitt/login"
      };
    }
    if (
      error instanceof EnlittLimitExceededError ||
      error instanceof EnlittInsufficientCreditsError ||
      error instanceof EnlittSubscriptionInactiveError
    ) {
      return {
        ok: false as const,
        message: "Review your Enlitt spending settings or credits.",
        href: error.authorizeUrl
      };
    }
    throw error; // Let your server's error handler log and handle other failures.
  }
}
```

## Retry behavior

Admission refusals such as login, spending, and exhausted-credit errors are
**non-retryable**. Repeating them cannot repair the user's account or settings.
`EnlittRateLimitError` (`rate_limit_exceeded`) is retryable and can carry
`retryAfterMs`. The SDK handles bounded rate-limit waiting; the defaults are
three attempts and a 30-second total wait budget. Set
`rateLimit: { maxAttempts: 1 }` to handle that wait yourself.

The codes `server_error` and `provider_error` also have a retryable marker.
The marker does not mean every SDK adapter automatically retries them.
Keep [the same idempotency identity](/docs/idempotency.md) when retrying a logical call.

Other Enlitt failures use the base `EnlittError` shape with their stable code,
including unknown codes from newer servers. Leave a fallback in code-based handling.
The base is documented as a type; use the named runtime subclasses in examples.
A premium provider's own errors are rethrown unchanged.

Terminal-report failures go to `onTerminalReportError`; they do not replace
successful provider output. Monitor that hook separately from user-facing failures.
