When a call to the Firebase PNV library fails, the library reports a
FirebasePhoneNumberVerificationException.
This page lists every error code that the exception can carry, when each one
occurs, and what your app should do about it.
This page assumes you've integrated Firebase PNV as described in Get started with Firebase Phone Number Verification on Android.
How errors are reported
Asynchronous methods (
getVerificationSupportInfo(),getVerifiedPhoneNumber(), and the custom flow methods) return aTask. When they fail, theTaskfails with aFirebasePhoneNumberVerificationException, which you receive inaddOnFailureListener.enableTestSession()is synchronous. It throws aFirebasePhoneNumberVerificationExceptiondirectly.
Read the exception's errorCode to find out what went wrong. The Firebase PNV codes
are constants in the
FirebasePnvStatusCodes
class. If the failure comes from Google Play services, errorCode can also be a
CommonStatusCodes
value, such as NETWORK_ERROR.
An unsupported device or SIM isn't an error. getVerificationSupportInfo()
succeeds and reports isSupported() as false for that SIM, and getReason()
tells you why. See Unsupported devices and SIMs.
Error codes
Test session setup
These errors are thrown synchronously by enableTestSession().
| Error code | Cause | Recommended action |
|---|---|---|
TEST_SESSION_ALREADY_ENABLED(55508) |
enableTestSession() was called more than once in the same
app process. FirebasePhoneNumberVerification.getInstance()
returns the same instance every time, so this also happens when an
Activity that calls it is recreated. |
Call enableTestSession() once per process, for example in
Application.onCreate(). See
Initialize the library in test
mode. |
INVALID_TEST_NUMBER_ID(55507) |
The test token passed to enableTestSession() is
empty. |
Make sure your build passes the token you generated in the
Firebase console, and only call enableTestSession() when the
token isn't empty. |
Verification
These errors fail the Task returned by getVerifiedPhoneNumber().
| Error code | Cause | Recommended action |
|---|---|---|
CREDENTIAL_MANAGER_ERROR(55506) |
Android Credential Manager didn't return the phone number. If the
exception's cause is a
GetCredentialCancellationException, the user most likely
dismissed the consent screen. |
Offer another way to verify the phone number, such as SMS. Don't retry automatically, because the user would see the consent screen again. |
CARRIER_NOT_SUPPORTED(55501) |
The carrier of the selected SIM isn't supported, or the device doesn't have the subscription information needed to verify it. | Fall back to another verification method, such as SMS. |
UNSUPPORTED_OPERATION(55505) |
Firebase PNV isn't available for this request on the device. | Fall back to another verification method, such as SMS. |
PREFLIGHT_CHECK_FAILED(55504) |
The Firebase PNV backend couldn't create the verification request, before the consent screen was shown. | Fall back to another verification method, such as SMS. If it happens for every request, check that your app is set up correctly (see Upgrade to production mode). |
INTEGRITY_CHECK_FAILED(55503) |
The device or app failed an integrity check. | Fall back to another verification method, such as SMS. |
INVALID_DIGITAL_CREDENTIAL_RESPONSE(55502) |
The response from Credential Manager couldn't be read, or couldn't be exchanged for a verified phone number. | Fall back to another verification method, such as SMS. |
INVALID_TEST_NUMBER_ID(55507) |
In test mode, the Firebase PNV backend rejected the test token, for example because it expired. Test tokens have a 7 day TTL. A rejected test token usually reports this code; if you see other errors in test mode, also check that your token is current. | Generate a new test token in the Firebase console and rebuild your app. |
ACTIVITY_CONTEXT_REQUIRED(55509) |
The Context passed to getVerifiedPhoneNumber()
isn't an Activity. The method needs an Activity to
show the consent screen. |
Pass the current Activity. This is a bug in your app, not
a condition to handle at runtime. |
Support check
The Task returned by getVerificationSupportInfo() fails only if the check
itself can't run. In that case, errorCode is either a Google Play services
CommonStatusCodes value or CARRIER_NOT_SUPPORTED. Treat the device as
unsupported and fall back to another verification method, such as SMS.
While a test session is enabled, getVerificationSupportInfo() doesn't contact
the Firebase PNV backend and always reports the test SIM as supported, even if the
test token has expired.
Custom flow
If you use the custom flow instead of
getVerifiedPhoneNumber():
getDigitalCredentialPayload()fails withPREFLIGHT_CHECK_FAILED, or withINVALID_TEST_NUMBER_IDif the backend rejects your test token.exchangeCredentialResponseForPhoneNumber()fails withINVALID_DIGITAL_CREDENTIAL_RESPONSE, or withINVALID_TEST_NUMBER_IDif the backend rejects your test token.- Your own call to Credential Manager throws a
GetCredentialException, which you handle directly.
Unsupported devices and SIMs
When isSupported() is false for a SIM, getReason() returns one of the
following
VerificationSupportStatus
values:
| Value | Meaning |
|---|---|
INCAPABLE_DUE_TO_CARRIER_UNSUPPORTED |
The SIM's carrier isn't supported. See Supported carriers. |
INCAPABLE_DUE_TO_ANDROID_VERSION |
The device runs a version of Android older than Android 9 (API level 28). |
INCAPABLE_DUE_TO_SIM_STATE |
The SIM isn't ready. A SIM that is locked or still loading can also report INCAPABLE_DUE_TO_CARRIER_UNSUPPORTED, because the carrier is checked first. |
In each case, use another verification method, such as SMS, for that SIM.
Example
The following example handles the errors that a typical app needs to
distinguish when calling getVerifiedPhoneNumber():
Kotlin
import android.util.Log
// Credential Manager is included with the Firebase PNV library.
import androidx.credentials.exceptions.GetCredentialCancellationException
import com.google.firebase.pnv.FirebasePhoneNumberVerification
import com.google.firebase.pnv.FirebasePhoneNumberVerificationException
import com.google.firebase.pnv.FirebasePnvStatusCodes
private const val TAG = "PhoneVerification"
// In your Activity:
private fun verifyPhoneNumber() {
FirebasePhoneNumberVerification.getInstance()
.getVerifiedPhoneNumber(this)
.addOnSuccessListener { result ->
// Send result.getToken() to your backend.
}
.addOnFailureListener { e -> handleFpnvError(e) }
}
private fun handleFpnvError(e: Exception) {
if (e !is FirebasePhoneNumberVerificationException) {
Log.w(TAG, "Firebase PNV failed", e)
showSmsVerification()
return
}
when (e.errorCode) {
FirebasePnvStatusCodes.CREDENTIAL_MANAGER_ERROR -> {
if (e.cause is GetCredentialCancellationException) {
// The user dismissed the consent screen.
}
showSmsVerification()
}
FirebasePnvStatusCodes.INVALID_TEST_NUMBER_ID -> {
// Test mode only: generate a new test token.
Log.e(TAG, "Firebase PNV test token rejected", e)
}
FirebasePnvStatusCodes.ACTIVITY_CONTEXT_REQUIRED -> {
// App bug: pass an Activity to getVerifiedPhoneNumber().
Log.e(TAG, "Firebase PNV needs an Activity context", e)
}
else -> {
// Carrier not supported, network errors, and other failures.
Log.w(TAG, "Firebase PNV failed with error code ${e.errorCode}", e)
showSmsVerification()
}
}
}
In this example, showSmsVerification() is your app's existing phone number
verification flow.
Next steps
- For details about each class and constant, see the Firebase PNV API reference.
- To verify the token on your server, see Verify Firebase PNV tokens.