Overview
Every async method in @authrim/web returns an AuthResponse<T> — a discriminated union that makes error handling type-safe and consistent:
| { data: T; error: null }
| { data: null; error: AuthError };
This means you never need try/catch for SDK methods. Check error first, then use data:
const { data, error } = await auth.passkey.login();
console.error(error.message);
// TypeScript knows data is non-null here
AuthError Structure
/** Authrim error code (e.g., 'AR003002') */
/** OAuth 2.0 error code (e.g., 'user_cancelled') */
/** Human-readable error message */
/** Whether the operation can be retried */
/** Error severity level */
severity: 'info' | 'warn' | 'error' | 'critical';
Error codes follow the pattern AR{domain}{number}:
| Prefix | Domain | Examples |
|---|
AR001 | Session / Auth | Session errors |
AR002 | Email Code | Send/verify errors |
AR003 | Passkey (WebAuthn) | Ceremony errors |
AR004 | Social Login | Provider/callback errors |
AR005 | OAuth / OIDC | Token/callback errors |
Severity Levels
| Level | Meaning | Typical Action |
|---|
info | Expected state (e.g., not authenticated) | Update UI normally |
warn | Recoverable issue (e.g., silent auth failed) | Log and continue |
error | Failed operation (e.g., invalid code) | Show error message |
critical | Unexpected failure (e.g., server error) | Show error + suggest retry |
Retryable Flag
showMessage('Something went wrong. Please try again.');
showMessage(error.message);
// Don't offer retry — issue needs user action
Error Handling Patterns
Basic Pattern
const { data, error } = await auth.passkey.login();
showErrorMessage(error.message);
Switch on Error Code
const { data, error } = await auth.emailCode.verify(email, code);
await auth.emailCode.send(email);
showMessage('Code expired. A new code has been sent.');
showMessage('Incorrect code. Please try again.');
showMessage('Too many attempts. Please wait before trying again.');
showMessage(error.message);
Severity-Based Handling
function handleAuthError(error: AuthError) {
switch (error.severity) {
// Not really an error — expected state
console.log(error.message);
// Recoverable — log but don't alert
console.warn(`[${error.code}] ${error.message}`);
showToast(error.message, 'error');
// Show prominently + log for debugging
showAlert(error.message);
Retry Pattern
async function loginWithRetry(maxRetries = 2) {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const { data, error } = await auth.passkey.login();
if (!error.retryable || attempt === maxRetries) {
showMessage(error.message);
// Brief delay before retry
await new Promise(resolve => setTimeout(resolve, 1000));
Error Codes Reference
Passkey (AR003xxx)
| Code | Error | Retryable | Description |
|---|
AR003000 | passkey_error | Varies | General passkey error |
AR003001 | webauthn_not_supported | No | Browser does not support WebAuthn |
AR003002 | user_cancelled | Yes | User cancelled the ceremony |
AR003003 | credential_not_found | No | No matching credential |
AR003004 | authenticator_error | Yes | Authenticator device error |
AR003005 | server_validation_failed | Yes | Server rejected the credential |
Email Code (AR002xxx)
| Code | Error | Retryable | Description |
|---|
AR002000 | email_code_error | Varies | General email code error |
AR002001 | invalid_email | No | Invalid email format |
AR002002 | rate_limited | No | Too many send requests |
AR002003 | code_expired | No | Verification code expired |
AR002004 | invalid_code | Yes | Wrong code entered |
AR002005 | max_attempts | No | Too many failed verifications |
Social Login (AR004xxx)
| Code | Error | Retryable | Description |
|---|
AR004001 | provider_not_configured | No | Provider not set up |
AR004002 | popup_blocked | No | Browser blocked the popup |
AR004003 | user_denied | Yes | User denied consent |
AR004004 | provider_error | Yes | Provider returned an error |
AR004005 | callback_failed | No | Callback validation failed |
OAuth (AR005xxx)
| Code | Error | Retryable | Description |
|---|
AR005001 | oauth_callback_error | No | Callback handling failed |
AR005002 | silent_auth_failed | No | Silent authentication failed |
AR005003 | no_tokens | No | No tokens received |
AR005004 | popup_login_error | Yes | Popup login failed |
Centralized Error Handler
Create a reusable error handler for your application:
function handleError(error: AuthError, context: string) {
console.error(`[${context}] ${error.code}: ${error.message}`);
if (error.severity === 'critical') {
showAlert('An unexpected error occurred. Please try again later.');
} else if (error.severity === 'error') {
showToast(error.message);
trackError({ code: error.code, context, severity: error.severity });
const { data, error } = await auth.passkey.login();
handleError(error, 'passkey-login');
Next Steps