The SDK never throws plain Error objects. Every failure is an IntelliAuthError with a stable code field you can branch on. This is the single error type your app needs to handle.
The shape
Section titled “The shape”class IntelliAuthError extends Error { code: IntelliAuthErrorCode // stable enum, listed below message: string // human-readable, may change between versions details?: Record<string, unknown> // extra context, code-specific cause?: unknown // wrapped underlying error if any recoverable: boolean // hint about whether a retry makes sense}Match on code. Do not match on message — message text is not part of the API and may improve over time without notice.
The codes
Section titled “The codes”The codes group into four families.
Session
Section titled “Session”| Code | When | Recoverable? |
|---|---|---|
session_expired | The user's session has expired since the last token refresh. | Yes — call loginWithRedirect(). |
session_revoked | An admin revoked the session, or the user revoked it from another device. | Yes — sign in again. |
not_authenticated | A method that requires a session was called without one. | Yes — sign in. |
silent_auth_failed | Background session check could not complete. | Sometimes — usually network. |
Auth flow
Section titled “Auth flow”| Code | When |
|---|---|
state_mismatch | The state returned to /callback does not match what the SDK sent. CSRF defence kicked in. |
invalid_redirect_uri | The redirect URI does not match what's registered on the application. |
consent_required | The user has not yet granted the requested scopes. |
mfa_required | The platform demands a second factor. Use completeMfaStep. |
step_up_required | The current AAL is too low for the action. Use stepUp. |
Network / platform
Section titled “Network / platform”| Code | When | Recoverable? |
|---|---|---|
network_error | The fetch itself failed (DNS, TCP, TLS). | Yes — retry with backoff. |
rate_limited | The user or app hit a rate limit. | Yes — wait, look for Retry-After. |
server_error | The platform returned a 5xx. | Yes — retry; consider a circuit breaker. |
not_found | The requested entity doesn't exist or you can't see it. | No — usually a config issue. |
MFA / credentials
Section titled “MFA / credentials”| Code | When |
|---|---|
webauthn_failed | The WebAuthn ceremony did not complete. |
totp_invalid | The submitted TOTP code was wrong or expired. |
sms_send_failed | The SMS delivery did not succeed. |
backup_code_invalid | The submitted backup code was wrong or already consumed. |
The error code index lists every code in the SDK with the recommended user-facing copy.
Branching pattern
Section titled “Branching pattern”const { loginWithRedirect } = useIntelliAuth()
async function trySignIn() { try { await loginWithRedirect() } catch (e) { if (!(e instanceof IntelliAuthError)) throw e
switch (e.code) { case 'mfa_required': // The SDK already started the MFA flow. Show the MFA step UI. showMfaPrompt(e.details?.flow_id) break case 'state_mismatch': // Don't retry silently — there may be a real CSRF attempt. showError('Sign-in security check failed. Please try again from the home page.') break case 'rate_limited': showError(`Too many attempts. Try again in ${e.details?.retry_after_s ?? 60}s.`) break default: showError(e.message) } }}Global error handler
Section titled “Global error handler”The provider supports onError. Use it for telemetry — not for user-facing UI:
<IntelliAuthProvider /* ... */ onError={(err) => { telemetry.captureException(err, { sdk: 'intelliauth' }) }}>Per-call try/catch is still required for user-facing branching; onError is the firehose.
Wrapping errors from other layers
Section titled “Wrapping errors from other layers”If you want to throw application-level errors that also happen to wrap an IntelliAuthError — say, a "PaymentBlockedError" that fires when MFA is required for a payment — use the cause:
try { await api.charge({ amount: 100 })} catch (e) { if (e instanceof IntelliAuthError && e.code === 'step_up_required') { throw new PaymentBlockedError('Confirm your identity to continue.', { cause: e }) } throw e}The downstream error handler can still match cause against IntelliAuthError when it needs to drive a step-up.
Logging
Section titled “Logging”IntelliAuthError serialises sensibly via JSON.stringify — code, message, details come out cleanly. The cause chain is not serialised by default; if you log via a structured logger, include cause explicitly.
Never log access tokens or refresh tokens. The SDK does not put them in error details; your code shouldn't either.