Skip to main content
The Auth0 Next.js SDK uses a hierarchical error class system for consistent error handling. All errors extend from the base SdkError class and include a code property for programmatic error identification.

Error Handling Pattern

Use error codes, not instanceof:
import { AccessTokenError, AccessTokenErrorCode } from "@auth0/nextjs-auth0/errors";

try {
  const { token } = await auth0.getAccessToken();
} catch (error) {
  if (error.code === AccessTokenErrorCode.MISSING_SESSION) {
    // User is not authenticated
    redirect("/auth/login");
  } else if (error.code === AccessTokenErrorCode.MISSING_REFRESH_TOKEN) {
    // No refresh token available
    console.error("Cannot refresh token - user must re-authenticate");
  }
}

Base Error Class

SdkError

Base class for all SDK errors.
abstract class SdkError extends Error {
  public abstract code: string;
}
Properties:
  • code: Unique error code for programmatic identification
  • message: Human-readable error description
  • name: Error class name

OAuth and Authorization Errors

OAuth2Error

Errors from Auth0 in the redirect_uri callback that may contain reflected user input.
Security: Do not render error or error_description properties without properly escaping them to prevent XSS vulnerabilities.
try {
  await auth0.handleCallback(request);
} catch (error) {
  if (error instanceof OAuth2Error) {
    // Sanitize before displaying to users
    console.error(`OAuth error [${error.code}]:`, error.message);
  }
}
Properties:
  • code: OAuth error code from Auth0
  • message: Error description

DiscoveryError

Code: discovery_error Thrown when OpenID Connect discovery fails.
try {
  const auth0 = new Auth0Client({ domain: "invalid-domain" });
} catch (error) {
  if (error.code === "discovery_error") {
    console.error("Failed to discover OIDC configuration");
  }
}

MissingStateError

Code: missing_state The state parameter is missing from the callback.

InvalidStateError

Code: invalid_state The state parameter in the callback is invalid or doesn’t match.

InvalidConfigurationError

Code: invalid_configuration The SDK configuration is invalid or incomplete.
try {
  const auth0 = new Auth0Client({}); // Missing required config
} catch (error) {
  if (error.code === "invalid_configuration") {
    console.error("Invalid SDK configuration:", error.message);
  }
}

AuthorizationError

Code: authorization_error An error occurred during the authorization flow. Properties:
  • cause: The underlying OAuth2Error
try {
  await auth0.handleCallback(request);
} catch (error) {
  if (error.code === "authorization_error") {
    console.error("Authorization failed:", error.cause?.message);
  }
}

AuthorizationCodeGrantRequestError

Code: authorization_code_grant_request_error Error occurred while preparing or performing the authorization code grant request.

AuthorizationCodeGrantError

Code: authorization_code_grant_error Error occurred while exchanging the authorization code for tokens. Properties:
  • cause: The underlying OAuth2Error

BackchannelLogoutError

Code: backchannel_logout_error Error occurred during backchannel logout request processing.

BackchannelAuthenticationNotSupportedError

Code: backchannel_authentication_not_supported_error The authorization server does not support backchannel authentication.
try {
  await auth0.backchannelAuthentication(params);
} catch (error) {
  if (error.code === "backchannel_authentication_not_supported_error") {
    console.error("Enable CIBA in Auth0 Dashboard:", error.message);
  }
}

BackchannelAuthenticationError

Code: backchannel_authentication_error Error when using Client-Initiated Backchannel Authentication. Properties:
  • cause: The underlying OAuth2Error (optional)

Access Token Errors

AccessTokenError

Errors related to access token retrieval or refresh. Error codes:
CodeValueDescription
MISSING_SESSIONmissing_sessionUser session not found
MISSING_REFRESH_TOKENmissing_refresh_tokenNo refresh token available for refresh
FAILED_TO_REFRESH_TOKENfailed_to_refresh_tokenToken refresh request failed
import { AccessTokenError, AccessTokenErrorCode } from "@auth0/nextjs-auth0/errors";

try {
  const { token } = await auth0.getAccessToken();
} catch (error) {
  if (error instanceof AccessTokenError) {
    switch (error.code) {
      case AccessTokenErrorCode.MISSING_SESSION:
        redirect("/auth/login");
        break;
      case AccessTokenErrorCode.MISSING_REFRESH_TOKEN:
        console.error("Re-authentication required");
        break;
      case AccessTokenErrorCode.FAILED_TO_REFRESH_TOKEN:
        console.error("Token refresh failed:", error.cause);
        break;
    }
  }
}
Properties:
  • code: Error code from AccessTokenErrorCode
  • cause: The underlying OAuth2Error (optional)

AccessTokenForConnectionError

Errors related to access tokens for specific connections. Error codes:
CodeValueDescription
MISSING_SESSIONmissing_sessionUser session not found
MISSING_REFRESH_TOKENmissing_refresh_tokenNo refresh token for connection
FAILED_TO_EXCHANGEfailed_to_exchange_refresh_tokenFailed to exchange refresh token
import { AccessTokenForConnectionError, AccessTokenForConnectionErrorCode } from "@auth0/nextjs-auth0/errors";

try {
  const token = await auth0.getAccessTokenForConnection("google-oauth2");
} catch (error) {
  if (error instanceof AccessTokenForConnectionError) {
    console.error(`Connection token error [${error.code}]:`, error.message);
  }
}
Properties:
  • code: Error code from AccessTokenForConnectionErrorCode
  • cause: The underlying OAuth2Error (optional)

CustomTokenExchangeError

Errors during custom token exchange operations. Error codes:
CodeValueDescription
MISSING_SUBJECT_TOKENmissing_subject_tokenSubject token is missing or empty
INVALID_SUBJECT_TOKEN_TYPEinvalid_subject_token_typeInvalid subject token type URI
MISSING_ACTOR_TOKEN_TYPEmissing_actor_token_typeActor token provided without type
EXCHANGE_FAILEDexchange_failedToken exchange request failed
import { CustomTokenExchangeError, CustomTokenExchangeErrorCode } from "@auth0/nextjs-auth0/errors";

try {
  await auth0.customTokenExchange(params);
} catch (error) {
  if (error instanceof CustomTokenExchangeError) {
    console.error(`Token exchange error [${error.code}]:`, error.message);
  }
}
Properties:
  • code: Error code from CustomTokenExchangeErrorCode
  • cause: The underlying OAuth2Error (optional)

DPoP Errors

DPoPError

Errors during DPoP (Demonstrating Proof-of-Possession) operations. Error codes:
CodeValueDescription
DPOP_JKT_CALCULATION_FAILEDdpop_jkt_calculation_failedFailed to calculate JWK thumbprint
DPOP_KEY_EXPORT_FAILEDdpop_key_export_failedFailed to export public key to JWK
DPOP_CONFIGURATION_ERRORdpop_configuration_errorInvalid DPoP configuration
import { DPoPError, DPoPErrorCode } from "@auth0/nextjs-auth0/errors";

try {
  const auth0 = new Auth0Client({
    useDPoP: true,
    dpopKeyPair: invalidKeyPair
  });
} catch (error) {
  if (error instanceof DPoPError) {
    switch (error.code) {
      case DPoPErrorCode.DPOP_KEY_EXPORT_FAILED:
        console.error("Invalid key format:", error.cause);
        break;
      case DPoPErrorCode.DPOP_JKT_CALCULATION_FAILED:
        console.error("JWK thumbprint calculation failed:", error.cause);
        break;
      case DPoPErrorCode.DPOP_CONFIGURATION_ERROR:
        console.error("Invalid DPoP configuration:", error.message);
        break;
    }
  }
}
Properties:
  • code: Error code from DPoPErrorCode
  • cause: The underlying error (optional)

MFA Errors

MfaRequiredError

Code: mfa_required Thrown when getAccessToken() requires MFA step-up authentication.
import { MfaRequiredError } from "@auth0/nextjs-auth0/errors";

try {
  const { token } = await auth0.getAccessToken({ audience: "https://api.example.com" });
} catch (error) {
  if (error instanceof MfaRequiredError) {
    // Redirect to MFA challenge page with encrypted token
    redirect(`/mfa?token=${error.mfa_token}`);
  }
}
Properties:
  • code: mfa_required
  • error: mfa_required
  • error_description: Error description from Auth0
  • mfa_token: Encrypted MFA token for use with MFA API methods
  • mfa_requirements: Available challenge/enrollment methods (optional)
  • cause: Underlying error (optional)
JSON serialization:
// Automatically serializes for HTTP responses
return Response.json(error, { status: 401 });
// Returns: { error: "mfa_required", error_description: "...", mfa_token: "..." }

InvalidRequestError

Code: invalid_request Request validation failed (missing or invalid parameters).
try {
  await mfa.verify({ mfaToken: "", otp: "123456" });
} catch (error) {
  if (error.code === "invalid_request") {
    return Response.json(error, { status: 400 });
  }
}

MfaGetAuthenticatorsError

Failed to list MFA authenticators.
import { MfaGetAuthenticatorsError } from "@auth0/nextjs-auth0/errors";

try {
  const authenticators = await mfa.getAuthenticators({ mfaToken });
} catch (error) {
  if (error instanceof MfaGetAuthenticatorsError) {
    console.error(error.error); // 'invalid_token', 'expired_token', etc.
    console.error(error.error_description);
    if (error.cause) {
      console.error("Auth0 API error:", error.cause);
    }
  }
}
Properties:
  • error: Auth0 error code
  • error_description: Error description
  • cause: Original Auth0 API error response (optional)

MfaChallengeError

Failed to initiate an MFA challenge.
import { MfaChallengeError } from "@auth0/nextjs-auth0/errors";

try {
  await mfa.challenge({
    mfaToken,
    challengeType: "oob",
    authenticatorId: "sms|dev_abc123"
  });
} catch (error) {
  if (error instanceof MfaChallengeError) {
    if (error.cause?.error === "invalid_authenticator_id") {
      console.error("Authenticator not found or not active");
    }
  }
}
Properties:
  • error: Auth0 error code
  • error_description: Error description
  • cause: Original Auth0 API error response (optional)

MfaVerifyError

MFA verification failed.
import { MfaVerifyError } from "@auth0/nextjs-auth0/errors";

try {
  await mfa.verify({ mfaToken, otp: "123456" });
} catch (error) {
  if (error instanceof MfaVerifyError) {
    if (error.cause?.error === "invalid_grant") {
      console.error("Invalid or expired verification code");
    }
  }
}
Properties:
  • error: Auth0 error code
  • error_description: Error description
  • cause: Original Auth0 API error response (optional)

MfaEnrollmentError

MFA enrollment failed.
import { MfaEnrollmentError } from "@auth0/nextjs-auth0/errors";

try {
  await mfa.enroll({ mfaToken, authenticatorTypes: ["otp"] });
} catch (error) {
  if (error instanceof MfaEnrollmentError) {
    if (error.cause?.error === "unsupported_challenge_type") {
      console.error("Tenant does not support OTP enrollment");
    }
  }
}
Properties:
  • error: Auth0 error code
  • error_description: Error description
  • cause: Original Auth0 API error response (optional)

MfaNoAvailableFactorsError

Code: mfa_no_available_factors No MFA factors are available for challenge. This is an SDK-generated error with no Auth0 API equivalent.

MfaTokenExpiredError

Code: mfa_token_expired The MFA token has expired. The user must restart the MFA flow.
try {
  await auth0.completeMfaChallenge(mfaToken, code);
} catch (error) {
  if (error.code === "mfa_token_expired") {
    redirect("/auth/login?prompt=mfa");
  }
}

MfaTokenInvalidError

Code: mfa_token_invalid The encrypted MFA token is invalid or has been tampered with.

My Account API Errors

MyAccountApiError

Code: my_account_api_error Error from Auth0’s My Account API.
import { MyAccountApiError } from "@auth0/nextjs-auth0/errors";

try {
  await fetch("/me/v1/profile");
} catch (error) {
  if (error instanceof MyAccountApiError) {
    console.error(`${error.title}: ${error.detail}`);
    console.error(`Status: ${error.status}`);
    if (error.validationErrors) {
      error.validationErrors.forEach(e => {
        console.error(`  - ${e.field}: ${e.detail}`);
      });
    }
  }
}
Properties:
  • code: my_account_api_error
  • type: Error type
  • title: Error title
  • detail: Error detail
  • status: HTTP status code
  • validationErrors: Array of validation errors (optional)

ConnectAccountError

Error during account linking flow. Error codes:
CodeValueDescription
MISSING_SESSIONmissing_sessionUser session not found
FAILED_TO_INITIATEfailed_to_initiateFailed to initiate connect flow
FAILED_TO_COMPLETEfailed_to_completeFailed to complete connect flow
import { ConnectAccountError, ConnectAccountErrorCodes } from "@auth0/nextjs-auth0/errors";

try {
  await auth0.connectAccount(connection);
} catch (error) {
  if (error instanceof ConnectAccountError) {
    console.error(`Connect error [${error.code}]:`, error.message);
    if (error.cause) {
      console.error("API error:", error.cause);
    }
  }
}
Properties:
  • code: Error code from ConnectAccountErrorCodes
  • cause: The underlying MyAccountApiError (optional)

Error Response Format

Many errors implement toJSON() for consistent HTTP response formatting:
try {
  await auth0.getAccessToken();
} catch (error) {
  if (error instanceof MfaRequiredError) {
    // Response.json() automatically calls toJSON()
    return Response.json(error, { status: 401 });
    // Returns:
    // {
    //   "error": "mfa_required",
    //   "error_description": "Multi-factor authentication required",
    //   "mfa_token": "encrypted-token",
    //   "mfa_requirements": { ... }
    // }
  }
}

Importing Errors

// Import from /errors path
import {
  SdkError,
  AccessTokenError,
  AccessTokenErrorCode,
  MfaRequiredError,
  InvalidConfigurationError,
  DPoPError,
  DPoPErrorCode
} from "@auth0/nextjs-auth0/errors";

Best Practices

Error codes are more reliable and work across module boundaries.
// Good
if (error.code === AccessTokenErrorCode.MISSING_SESSION) { ... }

// Avoid
if (error instanceof AccessTokenError) { ... }
OAuth errors may contain user input. Never render them directly.
if (error instanceof OAuth2Error) {
  // Sanitize before displaying
  const safe = escapeHtml(error.message);
}
Many errors include a cause property with the underlying error.
if (error.code === AccessTokenErrorCode.FAILED_TO_REFRESH_TOKEN) {
  console.error("OAuth error:", error.cause?.message);
}
Errors with toJSON() are designed for HTTP responses.
return Response.json(error, { status: 400 });

Build docs developers (and LLMs) love