Skip to content

Errors ​

Every failure in expo-apple-sign-in reaches your code as an AppleAuthError with a stable code, whichever platform produced it. The iOS module, the Android module, and the web flow report errors differently, and the JavaScript layer converts them into the same seven codes, so one switch statement covers all three platforms. This page lists the codes, the fields of the error, the helper functions, and a pattern for handling the result.

Codes ​

The codes are available at runtime as EAppleAuthErrorCode (also exported as AppleAuthErrorCode), for example EAppleAuthErrorCode.Canceled. The type TAppleAuthErrorCodeValue (alias AppleAuthErrorCodeValue) is the union of the seven code strings.

ConstantCodeMeaningTypical cause
CanceledERR_REQUEST_CANCELEDThe person dismissed the sign-in.iOS: the sheet was closed. Android: the close button or the system back action was used, the activity was destroyed before a result arrived, or the form posted to the redirect lacked state or carried none of id_token, code, and user. Web: Apple JS reported popup_closed_by_user, user_cancelled_authorize, or another code that contains cancel or closed.
FailedERR_REQUEST_FAILEDThe authorization attempt failed.iOS: the system reported failed, notHandled, notInteractive, or matchedExcludedCredential, or, on SDKs that declare them, credentialImport, credentialExport, preferSignInWithApple, or deviceNotConfiguredForPasskeyCreation. iOS also uses this code when no active window was available to present the sheet. iOS and Android: a sign-in was already running, and the message says that a Sign in with Apple request is already in progress. Android: no application context was available. Web: the browser blocked the popup (popup_blocked_by_browser), and the message asks you to call signIn from a click handler. Any platform: no secure random source was available for the nonce or state.
NotConfiguredERR_NOT_CONFIGUREDRequired configuration is missing or invalid.Android and web: clientId or redirectUri was not set through AppleAuth.configure. Web: redirectUri is not an absolute URL, or its origin differs from the page origin.
NotAvailableERR_NOT_AVAILABLESign in with Apple cannot run on this device.iOS and Android: the ExpoAppleSignIn native module is not linked (Expo Go, or a build made before the plugin was added). Web: there is no browser document, the Apple JS script failed to load, or it did not initialize. After a failed load, the next sign-in loads the script again.
MissingIdentityTokenERR_MISSING_IDENTITY_TOKENThe result contained no identity token.The native module or the Apple JS response returned no id_token. The error message names a cancel or a misconfigured Services ID or App ID as likely reasons.
InvalidResponseERR_INVALID_RESPONSEApple's response was not usable.iOS: the system reported invalidResponse, or returned a credential of an unexpected type. Android: the returned state differs from the one that was sent, or the form data posted to the redirect could not be read.
UnknownERR_REQUEST_UNKNOWNThe failure matches no other code.iOS: ASAuthorizationError.unknown, a code added by a later SDK, or an error that is not an ASAuthorizationError. Web: Apple JS rejected with a code the library does not map, and the message reads Apple sign-in failed: <code>. Any platform: an error with no recognizable code is normalized to this one.

AppleAuthError ​

AppleAuthError extends Error. Its name is 'AppleAuthError', and it adds these fields.

FieldTypeDescription
codestringOne of the codes above.
messagestringHuman-readable description.
causeunknownThe original error when the library wrapped one: a native rejection, an Apple JS SDK error, or any other thrown value. undefined when the library raised the error itself.

AppleAuth.request returns the same value as cause on its error response, and the AppleAuthError thrown by AppleAuth.signIn carries it too.

The constructor signature is new AppleAuthError(code: string, message: string, cause?: unknown).

Helpers ​

isAppleAuthError(error) is a type guard for AppleAuthError, based on instanceof.

isCancelledError(error) returns true for a cancel. For an AppleAuthError it compares the code with ERR_REQUEST_CANCELED. For any other object with a code property it also accepts ERR_CANCELED and 1001 as alternative cancel codes.

normalizeAppleError(error) converts anything into an AppleAuthError. It returns an existing AppleAuthError unchanged. For other objects, it applies these rules in order:

  1. If the code, name, or message text contains "cancel" (case-insensitive), the result has the code ERR_REQUEST_CANCELED.
  2. If code is a string that starts with ERR_, the result keeps that code and message.
  3. If the message has the shape ERR_SOMETHING: text, the code and text are split apart. This is the older Android form, still parsed as a fallback for errors that arrive without a code.
  4. Otherwise the result has the code ERR_REQUEST_UNKNOWN.

The same function runs inside AppleAuth.signIn, AppleAuth.request, the hook, and the button, so errors you receive from them already carry a normalized code.

Handle errors ​

lib/safe-sign-in.ts
ts
import { AppleAuth, EAppleAuthErrorCode, isAppleAuthError, isCancelledError } from 'expo-apple-sign-in'
import type { TAppleCredential } from 'expo-apple-sign-in'

export async function signInOrExplain(): Promise<TAppleCredential | null> {
  try {
    return await AppleAuth.signIn()
  } catch (error) {
    if (isCancelledError(error)) {
      return null
    }

    if (isAppleAuthError(error)) {
      switch (error.code) {
        case EAppleAuthErrorCode.NotConfigured:
          console.warn('Set clientId and redirectUri with AppleAuth.configure.')
          break
        case EAppleAuthErrorCode.NotAvailable:
          console.warn('Sign in with Apple is not available here. Use a development build.')
          break
        default:
          console.warn(`${error.code}: ${error.message}`)
      }
    }

    throw error
  }
}

If you prefer not to catch exceptions, AppleAuth.request() returns the same information as a value. See request and signIn. For fixes to the problems that cause these codes, see Troubleshooting.

Released under the MIT License.