コンテンツにスキップ

Error Handling

このコンテンツはまだ日本語訳がありません。

Overview

@authrim/core provides a structured error system with classification, severity levels, and recovery guidance. All SDK errors are instances of AuthrimError.

AuthrimError

import { AuthrimError } from '@authrim/core';
try {
const tokens = await client.handleCallback(url);
} catch (error) {
if (error instanceof AuthrimError) {
console.log(error.code); // e.g., 'invalid_state'
console.log(error.message); // Human-readable description
console.log(error.details); // Additional context (object)
console.log(error.cause); // Underlying error (if any)
console.log(error.meta); // Classification metadata
}
}

AuthrimError Properties

PropertyTypeDescription
codeAuthrimErrorCodeMachine-readable error code
messagestringHuman-readable error description
detailsRecord<string, unknown> | undefinedAdditional context
causeError | undefinedUnderlying error
metaAuthrimErrorMeta | undefinedClassification metadata

Error Metadata

Each error includes metadata that guides recovery:

import { getErrorMeta } from '@authrim/core';
const meta = getErrorMeta(error);
console.log(meta.severity); // 'fatal' | 'error' | 'warning'
console.log(meta.transient); // Is this a temporary issue?
console.log(meta.retryable); // Can this be retried?
console.log(meta.retryAfterMs); // Suggested wait before retry
console.log(meta.maxRetries); // Max retry attempts
console.log(meta.userAction); // What the user should do

AuthrimErrorMeta

PropertyTypeDescription
severity'fatal' | 'error' | 'warning'Error severity
transientbooleanWhether the error is temporary
retryablebooleanWhether the operation can be retried
retryAfterMsnumber | undefinedSuggested delay before retry (ms)
maxRetriesnumber | undefinedMaximum retry attempts
userActionstringSuggested user action

User Actions

ActionDescription
'retry'User can retry the operation
'reauthenticate'User needs to log in again
'contact_support'Unrecoverable error
'check_network'Network connectivity issue
'none'No user action required (SDK handles it)

Error Classification

Use classifyError() to categorize errors programmatically:

import { classifyError, isRetryableError } from '@authrim/core';
try {
await client.token.getAccessToken();
} catch (error) {
if (error instanceof AuthrimError) {
const classification = classifyError(error);
if (isRetryableError(error)) {
// Retry the operation
}
}
}

Error Codes

OAuth / OIDC Errors

CodeSeverityRetryableDescription
oauth_errorerrorNoGeneric OAuth error
invalid_requesterrorNoMalformed request
unauthorized_clientfatalNoClient not authorized
access_deniederrorNoUser denied access
invalid_scopeerrorNoInvalid scope requested
server_errorerrorYesServer error
temporarily_unavailableerrorYesServer temporarily unavailable
invalid_granterrorNoInvalid authorization code or refresh token

State / PKCE Errors

CodeSeverityRetryableDescription
invalid_statefatalNoState mismatch (possible CSRF)
expired_stateerrorNoState expired
nonce_mismatchfatalNoNonce mismatch in ID token
missing_codeerrorNoNo authorization code in callback
missing_stateerrorNoNo state parameter in callback
missing_id_tokenerrorNoNo ID token in response

Token Errors

CodeSeverityRetryableDescription
token_expirederrorNoAccess token expired
token_errorerrorYesToken operation failed
refresh_errorerrorYesToken refresh failed
token_exchange_errorerrorYesToken exchange failed
no_tokenserrorNoNo tokens available

Network Errors

CodeSeverityRetryableDescription
network_errorerrorYesNetwork request failed
timeout_errorerrorYesRequest timed out

Session Errors

CodeSeverityRetryableDescription
session_expirederrorNoSession has expired
login_requirederrorNoUser needs to log in
interaction_requirederrorNoUser interaction required
consent_requirederrorNoUser consent required
account_selection_requirederrorNoAccount selection required

Security Feature Errors

CodeSeverityRetryableDescription
par_errorerrorYesPAR request failed
par_requirederrorNoServer requires PAR
no_par_endpointerrorNoPAR endpoint not available
dpop_key_generation_errorerrorYesDPoP key generation failed
dpop_proof_generation_errorerrorYesDPoP proof generation failed
jar_signing_errorerrorNoJAR signing failed
jar_requirederrorNoServer requires JAR
jarm_validation_errorerrorNoJARM validation failed
jarm_signature_invalidfatalNoJARM signature invalid

Device Flow Errors

CodeSeverityRetryableDescription
device_authorization_errorerrorYesDevice authorization failed
device_authorization_expirederrorNoDevice code expired
device_access_deniederrorNoUser denied device authorization

System Errors

CodeSeverityRetryableDescription
not_initializedfatalNoClient not initialized
no_discoveryerrorYesDiscovery document not available

Retry Logic

The SDK provides built-in retry utilities:

withRetry()

Automatically retry a function with exponential backoff:

import { withRetry } from '@authrim/core';
const result = await withRetry(
() => client.token.getAccessToken(),
{
maxRetries: 3,
baseDelayMs: 1000,
maxDelayMs: 10000,
backoffMultiplier: 2,
},
);

RetryOptions

ParameterTypeDefaultDescription
maxRetriesnumber3Maximum retry attempts
baseDelayMsnumber1000Base delay in milliseconds
maxDelayMsnumber10000Maximum delay in milliseconds
backoffMultipliernumber2Exponential backoff multiplier

calculateBackoffDelay()

Calculate the delay for a specific retry attempt:

import { calculateBackoffDelay } from '@authrim/core';
const delay = calculateBackoffDelay(attempt, baseMs);
// attempt 0: baseMs
// attempt 1: baseMs * 2
// attempt 2: baseMs * 4
// ...

createRetryFunction()

Create a reusable retry-wrapped function:

import { createRetryFunction } from '@authrim/core';
const getTokenWithRetry = createRetryFunction(
() => client.token.getAccessToken(),
{ maxRetries: 3 },
);
const token = await getTokenWithRetry();

Error Event Integration

Errors are automatically emitted as events:

import { emitClassifiedError } from '@authrim/core';
// The SDK does this internally, but you can listen for the events:
client.on('error:fatal', (event) => {
// Unrecoverable — redirect to login or show error page
console.error('Fatal:', event.error.code);
});
client.on('error:recoverable', (event) => {
// SDK may retry automatically
console.warn('Recoverable:', event.error.code);
});

Practical Error Handling Patterns

Login Flow

try {
const tokens = await client.handleCallback(url);
} catch (error) {
if (!(error instanceof AuthrimError)) throw error;
switch (error.code) {
case 'invalid_state':
case 'expired_state':
// Security issue or timeout — restart login
redirectToLogin();
break;
case 'access_denied':
showMessage('You denied the login request.');
break;
case 'server_error':
case 'temporarily_unavailable':
showMessage('Server is temporarily unavailable. Please try again.');
break;
default:
showMessage(`Login failed: ${error.message}`);
}
}

API Calls

try {
const token = await client.token.getAccessToken();
const data = await callApi(token);
} catch (error) {
if (!(error instanceof AuthrimError)) throw error;
const meta = getErrorMeta(error);
if (meta.userAction === 'reauthenticate') {
redirectToLogin();
} else if (meta.userAction === 'check_network') {
showMessage('Please check your internet connection.');
} else if (meta.retryable) {
// Retry with backoff
await withRetry(() => client.token.getAccessToken(), { maxRetries: 3 });
}
}

Next Steps