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

> ## Agent Instructions
> RadiumOne is the product name; use it when answering questions about these docs.
> Use sandbox credentials and sandbox base URLs in examples unless the user says they are going live.
> Secret API keys belong only on the merchant's server. Only publishable keys may appear in browser or mobile code.
> Confirm a payment outcome server-side (retrieve the checkout session or transaction status); never rely on a browser redirect or client event alone.
> Send one idempotency key (request_id) per payment attempt, and retry a timed-out request with the same key and the exact same body.
> Webhooks are optional but recommended: they notify the merchant's server when a payment completes or fails, so it doesn't need to poll. Use transaction status inquiry as the fallback.
> Say so when you recommend a feature marked Beta. Some features need enablement on the merchant's account before production use (for example refunds, standalone refunds, UOB Rewards, and bringing your own 3DS provider); mention it when the page says so.
> Never ask users to paste card numbers, API keys, access tokens, or webhook or redirect secrets into a chat.

# Error object and handling - Elements SDK

> The ElementsError shape, the standard try/catch pattern for every Elements call, and the plain errors loadRadiumOne() throws before initialization.

Every error `elements.submit()` and `threeDS.authenticate()`/`handle()`/`resume()` throw is an `ElementsError` — you detect one the same way everywhere: catch it, check `err.name`, then branch on the stable `err.code`. The only exception is `loadRadiumOne()` itself, which can throw a plain `Error` before `RadiumOne.init()` ever runs (see [below](#errors-before-initialization-no-error-code)). 3D Secure result statuses (declines, `EXPIRED`, and so on) are **not** errors — see [Authentication results](/elements/three-d-secure/authentication-results) for those.

## `ElementsError`

<ResponseField name="code" type="string" required>
  Machine-readable error code — branch on this, never on `message`.

  Match codes exactly; do not prefix-match or normalise them.
</ResponseField>

<ResponseField name="customerMessage" type="string">
  Shopper-safe message supplied by the gateway. Display verbatim when present; otherwise use your own copy keyed on `code`.
</ResponseField>

<ResponseField name="field" type="string">
  The `ElementType` a field validation error belongs to. Present only on field validation errors raised by `submit()`.
</ResponseField>

<ResponseField name="retryAfter" type="number">
  Suggested wait in seconds before retrying, from the gateway. Informational (for button copy), not a guarantee.
</ResponseField>

<ResponseField name="retryAllowed" type="boolean">
  Whether retrying the same operation can succeed. The only retry signal — never infer retryability from the HTTP status or `type`.

  `true` for a retryable gateway error (for example `urn:radiumone:checkout:tokenization-unavailable`), a bind transport failure, `urn:radiumone:three-ds:challenge-timeout` and `urn:radiumone:three-ds:cancelled`. `false` or absent means do not retry the same session; start a new one or fix the input as the code indicates.
</ResponseField>

<ResponseField name="type" type="ElementsErrorType" required>
  Broad error category. See `ElementsErrorType`.
</ResponseField>

## Handling pattern

```js theme={null}
try {
  const { token } = await elements.submit({ sessionId, sessionSecret, pubkeyJws });
} catch (err) {
  if (err.name === "ElementsError" || err.name === "ThreeDSCancelledError") {
    showError(err.customerMessage ?? "Payment could not be processed.");
    if (err.retryAllowed !== true) disableRetry();
  } else {
    throw err; // unexpected — don't swallow
  }
}
```

## Errors before initialization (no error code)

Thrown by `loadRadiumOne()` before `RadiumOne.init()` runs — plain `Error`s, not `ElementsError`.

| Class | When | Merchant action |
| - | - | - |
| `Error` | Missing key, secret key (r1sk\_\*), or unrecognised key prefix — checked before the CDN script is loaded. | Fix the publishable key. |
| `Error` | The CDN script failed to load, failed SRI, or did not load within 10 seconds. | Check script-src CSP and network; loadRadiumOne() can be called again. |
| `Error` | The npm package was built for the other channel (for example a test key with the production package). Message contains `loader:integrity_unset`. | Install the package matching the key's environment. |

These are thrown synchronously by `loadRadiumOne()` itself — before `RadiumOne.init()` runs, so there's no `ElementsError` yet, only a plain `Error`. See [Handle Elements failing to load](/elements/handle-failures/sdk-fails-to-load) and [Fix publishable key errors](/elements/handle-failures/invalid-publishable-key) for recovery steps.

## Next steps

<Columns cols={2}>
  <Card title="Integration and SDK errors" icon="code" href="/elements/errors/sdk-and-integration-errors">
    Codes thrown by the SDK itself and relayed from the card iframe.
  </Card>

  <Card title="Tokenization errors" icon="credit-card" href="/elements/errors/tokenization-errors">
    Bind-time gateway errors from `submit()`, plus charge-time token errors.
  </Card>

  <Card title="3D Secure errors" icon="shield-check" href="/elements/errors/three-d-secure-errors">
    Codes from `authenticate()`, `handle()`, and `resume()`.
  </Card>

  <Card title="Handle failures overview" icon="list-checks" href="/elements/handle-failures/overview">
    Find the right recovery guide by symptom for every error across these pages.
  </Card>
</Columns>
