Auth0 Auth JS Error Classes and OAuth2Error Wrapping: A Complete Guide

The Auth0 Auth JS SDK exposes a hierarchy of domain-specific error classes that extend ApiError, each exposing a stable code string and preserving the raw OAuth 2.0 error payload in a cause property for full observability.

The auth0/auth0-auth-js repository provides a TypeScript SDK for OAuth 2.0 and OpenID Connect flows. When API calls fail, the SDK does not surface raw HTTP responses or generic Error objects. Instead, it normalizes every failure into strongly-typed error classes while preserving the original server-side error details for debugging and user-facing messages.

Error Class Hierarchy in auth0-auth-js

All error classes are defined in packages/auth0-auth-js/src/errors.ts. The architecture separates API-related failures from configuration or validation errors.

The ApiError Base Class

The abstract ApiError class serves as the foundation for all OAuth 2.0 flow failures:

abstract class ApiError extends Error {
  public cause?: OAuth2Error;
  public code: string;
  // ...
}
  • code: A machine-readable string that uniquely identifies the error type (e.g., token_by_code_error).
  • cause: Stores the original OAuth2Error payload from the Authorization Server, preserving the error, error_description, and optional message fields.

Concrete Error Classes

The SDK defines specific subclasses for every failure mode in the authentication lifecycle:

Error Class Code Value Thrown When
TokenByCodeError token_by_code_error getTokenByCode fails during authorization code exchange
TokenByClientCredentialsError token_by_client_credentials_error Client credentials flow fails
TokenByRefreshTokenError token_by_refresh_token_error Refresh token exchange fails
TokenExchangeError token_exchange_error RFC 8693 token exchange or Token Vault flows fail
TokenForConnectionError token_for_connection_error Legacy getTokenForConnection fails (backward-compatibility wrapper)
BuildAuthorizationUrlError build_authorization_url_error Authorization URL construction fails, including Pushed Authorization Requests (PAR)
BuildLinkUserUrlError build_link_user_url_error Link-user URL construction fails
BuildUnlinkUserUrlError build_unlink_user_url_error Unlink-user URL construction fails
BackchannelAuthenticationError backchannel_authentication_error CIBA flow initiation, polling, or grant fails
VerifyLogoutTokenError verify_logout_token_error Back-channel logout token validation fails
MissingClientAuthError missing_client_auth_error No client authentication method is configured
NotSupportedError Varies Feature not supported (e.g., PAR disabled, mTLS without custom fetch)

All classes extending ApiError inherit the cause property, allowing access to the raw OAuth 2.0 error response.

How the SDK Wraps OAuth2Error Exceptions

The SDK uses openid-client for underlying HTTP calls. When that library throws, the SDK assumes the object conforms to the OAuth2Error interface and wraps it in a domain-specific class.

The OAuth2Error Interface

Raw errors from the Authorization Server match this structure, defined in packages/auth0-auth-js/src/errors.ts:

export interface OAuth2Error {
  error: string;
  error_description: string;
  message?: string;
}

Error Wrapping Pattern

In packages/auth0-auth-js/src/auth-client.ts, every public method follows a consistent pattern. For example, buildAuthorizationUrl implements:

try {
  return await this.#buildAuthorizationUrl(options);
} catch (e) {
  // e is expected to be an OAuth2Error from openid-client
  throw new BuildAuthorizationUrlError(e as OAuth2Error);
}

The constructor of the specific error class forwards the OAuth2Error to the ApiError base class, which stores it in this.cause. This preserves the full server response while providing a stable SDK error type.

Accessing the Original Error

Consumers can inspect both the SDK error classification and the underlying OAuth 2.0 failure:

try {
  await authClient.buildAuthorizationUrl(opts);
} catch (err) {
  if (err instanceof BuildAuthorizationUrlError) {
    console.error('SDK error code:', err.code);
    console.error('OAuth2 error:', err.cause?.error);
    console.error('Description:', err.cause?.error_description);
  }
}

Practical Error Handling Examples

Handling Token Exchange Failures

When performing RFC 8693 token exchanges:

import { AuthClient, TokenExchangeError } from '@auth0/auth0-auth-js';

const client = new AuthClient({
  domain: 'my-tenant.auth0.com',
  clientId: 'YOUR_CLIENT_ID',
  clientSecret: 'YOUR_CLIENT_SECRET',
});

(async () => {
  try {
    const resp = await client.exchangeToken({
      connection: 'google-oauth2',
      subjectToken: 'bad-token',
    });
    console.log('Token:', resp.accessToken);
  } catch (err) {
    if (err instanceof TokenExchangeError) {
      console.error('Exchange failed – code:', err.code);
      console.error('OAuth error:', err.cause?.error);
      console.error('Details:', err.cause?.error_description);
    } else {
      console.error('Unexpected error:', err);
    }
  }
})();

Validating Logout Tokens

When verifying back-channel logout tokens:

import { AuthClient, VerifyLogoutTokenError } from '@auth0/auth0-auth-js';

(async () => {
  try {
    const result = await client.verifyLogoutToken({ 
      logoutToken: 'invalid.jwt.token' 
    });
    console.log('Logout token valid for SID:', result.sid);
  } catch (err) {
    if (err instanceof VerifyLogoutTokenError) {
      console.error('Logout token verification failed –', err.message);
      console.error('Error code:', err.code);
    }
  }
})();

Summary

  • The Auth0 Auth JS SDK defines a hierarchy of error classes in packages/auth0-auth-js/src/errors.ts, all extending the abstract ApiError base class.
  • Every API error exposes a stable code string (e.g., token_by_code_error) for programmatic error handling.
  • Raw OAuth 2.0 errors from the Authorization Server are preserved in the cause property, which implements the OAuth2Error interface with error, error_description, and optional message fields.
  • Public methods in auth-client.ts wrap underlying openid-client failures using a consistent try-catch pattern, converting raw errors into domain-specific classes like TokenExchangeError or BuildAuthorizationUrlError.

Frequently Asked Questions

What is the base class for all API errors in Auth0 Auth JS?

The abstract ApiError class defined in packages/auth0-auth-js/src/errors.ts serves as the base for all API-related errors. It extends the native JavaScript Error class and adds a code property for machine-readable error identification and an optional cause property that stores the original OAuth2Error from the Authorization Server.

How can I access the original OAuth 2.0 error description when catching SDK errors?

Access the cause property on any caught error that extends ApiError. The cause object implements the OAuth2Error interface and contains error (the OAuth error code), error_description (the human-readable explanation), and an optional message field. For example: err.cause?.error_description.

Which error class is thrown when the authorization URL fails to build?

The SDK throws BuildAuthorizationUrlError when constructing the authorization URL fails, including during Pushed Authorization Requests (PAR). This error has the code build_authorization_url_error and will contain the underlying OAuth 2.0 error in its cause property if the failure originated from the Authorization Server.

Does Auth0 Auth JS throw different errors for each token endpoint flow?

Yes. The SDK provides distinct error classes for each token acquisition method: TokenByCodeError for authorization code exchanges, TokenByClientCredentialsError for client credentials, TokenByRefreshTokenError for refresh token flows, and TokenExchangeError for RFC 8693 token exchanges. Each class has a unique code string identifying the specific flow that failed.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →