Skip to content

Error Handling

Direct Auth and OAuth methods in @authrim/web return an AuthResponse<T> — a discriminated union that makes error handling type-safe and consistent:

type AuthResponse<T> =
| { data: T; error: null }
| { data: null; error: AuthError };

For these methods, check error first, then use data:

const { data, error } = await auth.passkey.login();
if (error) {
// Handle error
console.error(error.message);
return;
}
// TypeScript knows data is non-null here
console.log(data.user);

Protected-resource helpers such as auth.stepUp, auth.customerProfiles, auth.devices, and auth.fetch() call HTTP APIs directly. Use try/catch around those methods when you need to handle request failures.

interface AuthError {
/** Authrim error code (e.g., 'AR003002') */
code: string;
/** OAuth 2.0 error code (e.g., 'user_cancelled') */
error: string;
/** Human-readable error message */
message: string;
/** Whether the operation can be retried */
retryable: boolean;
/** Error severity level */
severity: 'info' | 'warn' | 'error' | 'critical';
}

Error codes follow the pattern AR{domain}{number}:

PrefixDomainExamples
AR001Session / AuthSession errors
AR002Email CodeSend/verify errors
AR003Passkey (WebAuthn)Ceremony errors
AR004Social LoginProvider/callback errors
AR005OAuth / OIDCToken/callback errors
LevelMeaningTypical Action
infoExpected state (e.g., not authenticated)Update UI normally
warnRecoverable issue (e.g., silent auth failed)Log and continue
errorFailed operation (e.g., invalid code)Show error message
criticalUnexpected failure (e.g., server error)Show error + suggest retry
if (error.retryable) {
showMessage('Something went wrong. Please try again.');
// Offer retry button
} else {
showMessage(error.message);
// Don't offer retry — issue needs user action
}
const { data, error } = await auth.passkey.login();
if (error) {
showErrorMessage(error.message);
return;
}
// Success
redirect('/dashboard');
const { data, error } = await auth.emailCode.verify(email, code);
if (error) {
switch (error.code) {
case 'AR002003':
// Code expired — resend
await auth.emailCode.send(email);
showMessage('Code expired. A new code has been sent.');
break;
case 'AR002004':
// Wrong code
showMessage('Incorrect code. Please try again.');
break;
case 'AR002005':
// Too many attempts
showMessage('Too many attempts. Please wait before trying again.');
break;
default:
showMessage(error.message);
}
return;
}
function handleAuthError(error: AuthError) {
switch (error.severity) {
case 'info':
// Not really an error — expected state
console.log(error.message);
break;
case 'warn':
// Recoverable — log but don't alert
console.warn(`[${error.code}] ${error.message}`);
break;
case 'error':
// Show to user
showToast(error.message, 'error');
break;
case 'critical':
// Show prominently + log for debugging
showAlert(error.message);
logToService(error);
break;
}
}
async function loginWithRetry(maxRetries = 2) {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const { data, error } = await auth.passkey.login();
if (!error) {
return data;
}
if (!error.retryable || attempt === maxRetries) {
showMessage(error.message);
return null;
}
// Brief delay before retry
await new Promise(resolve => setTimeout(resolve, 1000));
}
return null;
}
CodeErrorRetryableDescription
AR003000passkey_errorVariesGeneral passkey error
AR003001webauthn_not_supportedNoBrowser does not support WebAuthn
AR003002user_cancelledYesUser cancelled the ceremony
AR003003credential_not_foundNoNo matching credential
AR003004authenticator_errorYesAuthenticator device error
AR003005server_validation_failedYesServer rejected the credential
CodeErrorRetryableDescription
AR002000email_code_errorVariesGeneral email code error
AR002001invalid_emailNoInvalid email format
AR002002rate_limitedNoToo many send requests
AR002003code_expiredNoVerification code expired
AR002004invalid_codeYesWrong code entered
AR002005max_attemptsNoToo many failed verifications
CodeErrorRetryableDescription
AR004001provider_not_configuredNoProvider not set up
AR004002popup_blockedNoBrowser blocked the popup
AR004003user_deniedYesUser denied consent
AR004004provider_errorYesProvider returned an error
AR004005callback_failedNoCallback validation failed
CodeErrorRetryableDescription
AR005001oauth_callback_errorNoCallback handling failed
AR005002silent_auth_failedNoSilent authentication failed
AR005003no_tokensNoNo tokens received
AR005004popup_login_errorYesPopup login failed

Create a reusable error handler for your application:

function handleError(error: AuthError, context: string) {
// Log all errors
console.error(`[${context}] ${error.code}: ${error.message}`);
// User-facing message
if (error.severity === 'critical') {
showAlert('An unexpected error occurred. Please try again later.');
} else if (error.severity === 'error') {
showToast(error.message);
}
// Analytics
trackError({ code: error.code, context, severity: error.severity });
}
// Usage
const { data, error } = await auth.passkey.login();
if (error) {
handleError(error, 'passkey-login');
return;
}