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

# Error Handling

> Handle OzError instances from createToken() and createBankToken(), understand error codes, and surface errors to users.

`createToken()` and `createBankToken()` both throw an `OzError` when tokenization fails. Wrap calls in a `try/catch` and inspect `.errorCode` to decide how to respond.

***

## OzError

```ts theme={null}
import { OzError } from '@ozura/elements';

try {
  const { token } = await vault.createToken();
} catch (err) {
  if (err instanceof OzError) {
    console.error(err.message);    // user-facing message
    console.error(err.errorCode);  // machine-readable code
    console.error(err.raw);        // raw message from vault (for logging)
    console.error(err.retryable);  // boolean: safe to retry?
  }
}
```

### OzError properties

| Property    | Type          | Description                                                                                                                                 |
| ----------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `message`   | `string`      | Normalized, user-friendly error message                                                                                                     |
| `errorCode` | `OzErrorCode` | Machine-readable code (see table below)                                                                                                     |
| `raw`       | `string`      | Raw message returned by the Vault API (use for logging, not display)                                                                        |
| `retryable` | `boolean`     | `true` for transient errors (`network`, `timeout`, `server`). `false` for permanent failures where retrying with the same input won't help. |

***

## Error Codes

| `errorCode`    | `retryable` | Meaning                                                                               | What to do                                                                                                                                                                                |
| -------------- | ----------- | ------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `'network'`    | ✅           | Request failed due to a network error (offline, DNS failure, etc.)                    | Show a "check your connection" message. Retry is safe.                                                                                                                                    |
| `'timeout'`    | ✅           | Tokenization took longer than 30 seconds                                              | Show a timeout message. Retry is safe.                                                                                                                                                    |
| `'server'`     | ✅           | Vault returned a 5xx error                                                            | Retry after a short delay. Log for investigation.                                                                                                                                         |
| `'auth'`       | ❌           | Session key invalid/expired (after automatic refresh retry), or pub key misconfigured | If you see this in production after a successful initial load, the auto-refresh failed — check that your session endpoint (`/api/oz-session`) is reachable. Otherwise verify credentials. |
| `'validation'` | ❌           | Request was malformed or the vault rejected input                                     | Check request parameters. Usually a developer error.                                                                                                                                      |
| `'config'`     | ❌           | Unexpected SDK or environment issue                                                   | Log the error and contact Ozura support.                                                                                                                                                  |
| `'unknown'`    | ❌           | Unclassified error                                                                    | Log and surface a generic message.                                                                                                                                                        |

<Note>
  **Session key expiry is handled automatically.** When a session key expires or is consumed between initialization and the user clicking Pay, the SDK silently fetches a fresh key and retries once. You will only receive an `auth` error if the refresh itself fails (e.g. your session endpoint is down or returns an error). The proactive refresh — triggered once `sessionLimit` successful submissions are reached — also prevents expiry from surfacing under normal usage.
</Note>

***

## Recommended Pattern

```ts theme={null}
import { OzVault, OzError } from '@ozura/elements';

async function handlePay() {
  try {
    const { token, cvcSession } = await vault.createToken({
      billing: { firstName: 'Jane', lastName: 'Smith' },
    });

    await submitPayment(token, cvcSession);

  } catch (err) {
    if (!(err instanceof OzError)) throw err; // rethrow unexpected errors

    if (err.retryable) {
      showError('Connection issue — please try again.');
    } else {
      switch (err.errorCode) {
        case 'auth':
          showError('Configuration error. Please contact support.');
          console.error('[OzElements] Auth error:', err.raw);
          break;

        case 'validation':
          showError('Payment details could not be verified. Please check your card.');
          break;

        case 'config':
          showError('Configuration error. Please contact support.');
          console.error('[OzElements] Config error:', err.raw);
          break;

        default:
          showError('Something went wrong. Please try again.');
          console.error('[OzElements] Unexpected error:', err);
      }
    }
  }
}
```

***

## SDK-Level Errors

These `OzError` instances are thrown before any network request is made. They represent setup or usage mistakes caught during integration — fix them in code, don't surface them to the user.

### Initialization errors

These come from `OzVault.create()`. If you're using the React provider, they appear in `initError`.

| Condition                                                | How to fix                                                                                                                                                                                 |
| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `pubKey` missing                                         | If using a **production** vault API key, pass a valid `pubKey` to `OzVault.create()` / `<OzElements>`. If using a test/sandbox vault API key, `pubKey` is not required and can be omitted. |
| No session option provided                               | Pass `sessionUrl`, `getSessionKey`, or (deprecated) `fetchWaxKey` to `OzVault.create()` / `<OzElements>`.                                                                                  |
| `sessionUrl` or `getSessionKey` returned an empty string | Check your `/api/oz-session` endpoint — it must return a non-empty `sessionKey`.                                                                                                           |
| Session fetch threw an error                             | Your session endpoint failed. Check server logs.                                                                                                                                           |

### Tokenization errors

These come from `createToken()` / `createBankToken()`.

| Condition                                          | How to fix                                                                                                |
| -------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| Vault not ready                                    | Wait for the `onReady` callback (vanilla) or the `ready` flag (React) before submitting.                  |
| No elements mounted                                | Call `mount()` on at least one element before tokenizing.                                                 |
| `accountNumber` / `routingNumber` not ready (bank) | Mount both bank elements before calling `createBankToken()`.                                              |
| Tokenization already in progress                   | Disable your submit button while tokenization is pending.                                                 |
| Missing `firstName` / `lastName` (bank)            | Pass `firstName` and `lastName` in your `createBankToken()` options.                                      |
| Name exceeds 50 characters                         | Truncate or validate `firstName` / `lastName` before submitting.                                          |
| Invalid billing details                            | Validate `billing` fields before calling `createToken()`. Check the error message for the specific field. |
| Tokenization timed out                             | `errorCode: 'timeout'` — retryable; show a timeout message.                                               |

### Element errors

| Condition                             | How to fix                                                                          |
| ------------------------------------- | ----------------------------------------------------------------------------------- |
| `mount()` CSS selector not found      | Verify the selector string targets an element that exists in the DOM at mount time. |
| `mount()` passed `null` / `undefined` | Check your DOM reference before calling `mount()`.                                  |

These are developer errors — TypeScript types and the error messages above are the full diagnostic.

***

## Load Errors

If the vault fails to load (network issue, blocked by CSP, etc.), use `onLoadError` in `OzVault.create()`:

```ts theme={null}
const vault = await OzVault.create({
  pubKey:      'YOUR_PUB_KEY',
  sessionUrl:  '/api/oz-session',
  onLoadError: () => {
    showError('Payment fields could not load. Please refresh and try again.');
  },
  loadTimeoutMs: 8000, // default: 10000
});
```

Individual element load failures emit a `loaderror` event with the element type and error message:

```ts theme={null}
cardNumber.on('loaderror', ({ elementType, error }) => {
  console.error(`[OzElements] ${elementType} failed to load:`, error);
  showError('Card number field failed to load. Please refresh.');
});
```

***

## React: initError

In React, `OzVault.create()` is called inside the `<OzElements>` provider. If it fails (e.g. your session endpoint is unreachable or returns an error), `useOzElements().initError` will be non-null:

```tsx theme={null}
function CheckoutForm() {
  const { createToken, ready, initError } = useOzElements();

  if (initError) {
    return <p>Payment unavailable — please refresh the page.</p>;
  }

  return (
    <form onSubmit={handleSubmit}>
      <OzCard />
      <button type="submit" disabled={!ready}>Pay</button>
    </form>
  );
}
```

***

## Error Normalization Helpers

The SDK exports three standalone functions that map raw API error strings to user-friendly messages.

<Note>
  `OzError.message` from `createToken()` and `createBankToken()` is **already normalized** — the SDK calls these functions internally. You only need to call them yourself when you receive raw error strings from a different source (e.g. your backend forwarding a vault or OzuraPay API response).
</Note>

### normalizeVaultError

Maps raw vault `/tokenize` error strings to user-facing messages for **card** flows.

```ts theme={null}
import { normalizeVaultError } from '@ozura/elements';

const message = normalizeVaultError(rawVaultErrorString);
// e.g. "Invalid card number" → "The card number is invalid. Please check and try again."
```

### normalizeBankVaultError

Maps raw vault `/tokenize` error strings to user-facing messages for **bank/ACH** flows.

```ts theme={null}
import { normalizeBankVaultError } from '@ozura/elements';

const message = normalizeBankVaultError(rawVaultErrorString);
// e.g. "Invalid routing number" → "The routing number is invalid. Please check and try again."
```

### normalizeCardSaleError

Maps raw OzuraPay API `cardSale` error strings to user-facing messages. Use this when your backend processes a charge via the OzuraPay API and needs to display the error to the user.

```ts theme={null}
import { normalizeCardSaleError } from '@ozura/elements';

const message = normalizeCardSaleError(rawPayApiErrorString);
// e.g. "Insufficient Funds" → "Your card has insufficient funds. Please use a different payment method."
```

All three functions fall back gracefully when no pattern matches:

* **`normalizeVaultError`** and **`normalizeBankVaultError`** — return the original `raw` string unchanged when no pattern matches.
* **`normalizeCardSaleError`** — short unrecognized strings (under 100 characters) are returned as-is; long opaque server strings (100+ characters) are replaced with `"Payment processing failed. Please try again or contact support."` An empty input returns `"Payment processing failed. Please try again."`

***

## Next Steps

<CardGroup cols={2}>
  <Card title="API Reference" icon="book" href="/sdks/elements/api-reference">
    Full OzError type definition and all SDK types.
  </Card>

  <Card title="Card Elements" icon="credit-card" href="/sdks/elements/card-elements">
    createToken() full reference.
  </Card>
</CardGroup>
