Overview
@authrim/server provides a structured error system with 27 error codes across 7 categories. Every error includes metadata for HTTP status, transient classification, and retryability — enabling you to build correct error responses automatically.
AuthrimServerError
All errors thrown by the SDK are instances of AuthrimServerError:
import { AuthrimServerError } from ' @authrim/server ' ;
const token = await server . validateToken (accessToken);
if (error instanceof AuthrimServerError ) {
console . log (error . code ); // e.g., 'token_expired'
console . log (error . message ); // Human-readable description
console . log (error . meta ); // { httpStatus, transient, retryable, wwwAuthenticateError }
Properties
Property Type Description codestringMachine-readable error code (see table below) messagestringHuman-readable error description metaAuthrimServerErrorMetaClassification metadata
Property Type Description httpStatusnumberRecommended HTTP status code for the response transientbooleanWhether the error is temporary and may resolve on its own retryablebooleanWhether the operation can be safely retried wwwAuthenticateErrorstring | undefinedError code for the WWW-Authenticate header (RFC 6750)
Error Code Reference
JWT Validation Errors
Code HTTP Status Transient Retryable Description invalid_token401 No No Token is invalid (general validation failure) token_expired401 No No Token has expired (exp claim) token_not_yet_valid401 No No Token is not yet valid (nbf claim) token_malformed401 No No Token cannot be decoded or parsed signature_invalid401 No No JWT signature verification failed algorithm_mismatch401 No No Token algorithm does not match expected algorithms
Issuer / Audience Errors
Code HTTP Status Transient Retryable Description invalid_issuer401 No No Token issuer does not match expected issuer invalid_audience401 No No Token audience does not include expected audience
JWKS Errors
Code HTTP Status Transient Retryable Description jwks_fetch_error502 Yes Yes Failed to fetch the JWKS document jwks_key_not_found401 No No No matching key found in JWKS for the token’s kid jwks_key_ambiguous401 No No Multiple keys match the token’s kid jwks_key_import_error500 No No Failed to import a JWK for signature verification
DPoP Errors
Code HTTP Status Transient Retryable Description dpop_proof_missing401 No No DPoP proof header is missing dpop_proof_invalid401 No No DPoP proof is malformed or invalid dpop_proof_signature_invalid401 No No DPoP proof signature verification failed dpop_method_mismatch401 No No HTTP method in DPoP proof does not match request dpop_uri_mismatch401 No No URI in DPoP proof does not match request URL dpop_ath_mismatch401 No No Access token hash in DPoP proof does not match dpop_binding_mismatch401 No No DPoP proof key does not match token binding dpop_iat_expired401 No No DPoP proof iat is too old dpop_nonce_required401 No No Server requires a DPoP nonce but none was provided
Operation Errors
Code HTTP Status Transient Retryable Description introspection_error502 Yes Yes Token introspection request failed revocation_error502 Yes Yes Token revocation request failed
Configuration Errors
Code HTTP Status Transient Retryable Description configuration_error500 No No Invalid SDK configuration provider_error500 No No Provider implementation error
Network Errors
Code HTTP Status Transient Retryable Description network_error502 Yes Yes Network request failed timeout_error504 Yes Yes Request timed out
Response Utilities
Generates an RFC 6750 compliant WWW-Authenticate header value:
import { buildWwwAuthenticateHeader } from ' @authrim/server ' ;
const header = buildWwwAuthenticateHeader (error , {
// Bearer realm="my-api", error="invalid_token", error_description="Token has expired"
Options:
Option Type Description realmstringRealm value for the header
buildErrorResponse()
Generates a JSON error body suitable for HTTP responses:
import { buildErrorResponse } from ' @authrim/server ' ;
const body = buildErrorResponse (error);
// error: 'invalid_token',
// error_description: 'Token has expired'
Generates response headers including WWW-Authenticate:
import { buildErrorHeaders } from ' @authrim/server ' ;
const headers = buildErrorHeaders (error , { realm: ' my-api ' } );
// 'WWW-Authenticate': 'Bearer realm="my-api", error="invalid_token", ...',
// 'Content-Type': 'application/json'
Error Handling in Middleware
All framework adapters accept an onError callback for logging and monitoring:
import { authrimMiddleware } from ' @authrim/server/adapters/express ' ;
authrimMiddleware (server, {
// Log to your monitoring service
httpStatus: error . meta . httpStatus ,
transient: error . meta . transient ,
metrics . increment ( ' auth.error ' , { code: error . code });
Middleware Error Behavior
When using the required middleware (e.g., authrimMiddleware), the adapter automatically returns the correct HTTP status code and WWW-Authenticate header. The onError callback is for observability only — it does not change the response.
Framework-Specific Error Patterns
Express
} from ' @authrim/server ' ;
app . get ( ' /api/resource ' , async ( req , res ) => {
const token = await server . validateToken (
req . headers . authorization ?. replace ( ' Bearer ' , '' ) ?? '' ,
res . json ({ data: getResource (token . sub ) });
if (error instanceof AuthrimServerError ) {
const headers = buildErrorHeaders (error , { realm: ' my-api ' } );
const body = buildErrorResponse (error);
return res . status (error . meta . httpStatus ) . set (headers) . json (body);
res . status ( 500 ) . json ({ error: ' internal_error ' });
Hono
import { AuthrimServerError, buildErrorResponse } from ' @authrim/server ' ;
app . get ( ' /api/resource ' , async ( c ) => {
const token = await server . validateToken (
c . req . header ( ' authorization ' ) ?. replace ( ' Bearer ' , '' ) ?? '' ,
return c . json ({ data: getResource (token . sub ) });
if (error instanceof AuthrimServerError ) {
return c . json ( buildErrorResponse (error), error . meta . httpStatus );
return c . json ({ error: ' internal_error ' }, 500 );
Retry Strategy for Transient Errors
Transient errors (network issues, JWKS fetch failures) can be retried. Use the meta.transient and meta.retryable flags to build retry logic:
import { AuthrimServerError } from ' @authrim/server ' ;
async function validateWithRetry (
) : Promise < ValidatedToken > {
let lastError : AuthrimServerError | undefined ;
for ( let attempt = 0 ; attempt <= maxRetries; attempt ++ ) {
return await server . validateToken (token);
if ( ! (error instanceof AuthrimServerError )) throw error;
// Only retry transient, retryable errors
if ( ! error . meta . retryable || attempt === maxRetries) {
// Exponential backoff: 100ms, 200ms, 400ms
const delay = 100 * Math . pow ( 2 , attempt);
await new Promise ( ( resolve ) => setTimeout (resolve , delay));
Do Not Retry Non-Transient Errors
Errors like invalid_token, token_expired, and signature_invalid are not transient — the same input will always produce the same error. Only retry when error.meta.retryable is true.
Transient vs Non-Transient Summary
Category Transient Retryable Action JWT Validation No No Return 401 immediately Issuer/Audience No No Return 401 immediately DPoP No No Return 401 immediately JWKS Fetch Yes Yes Retry with backoff Operations (introspection/revocation) Yes Yes Retry with backoff Network Yes Yes Retry with backoff Configuration No No Fix configuration and restart
Next Steps