Admin SDK error handling

Note: Error handling guidance provided in this guide applies to all Admin SDKimplementationsexcept Node.js.

Admin SDK errors are divided into two categories:

  1. Programming errors: These are programming and configuration errors inthe user application. They mostly occur due to the incorrect usage of the SDK(such as passingnull to a method that doesn’t acceptnull values), andother configuration errors at the Firebase project or SDK level (missingcredentials, incorrect project ID string, and so on).
  2. API errors: Theseinclude various recoverable errors that occur within the SDK implementation, allthe errors that originate in Firebase backend services, and other transienterrors (such as timeouts) that may occur while making RPC calls.

The Admin SDK signalsprogramming errors by throwing an error that is native tothe platform in question.

  • Java: Throws instances ofIllegalArgumentException,NullPointerExceptionor similar built-in runtime error type.
  • Python: Raises instances ofValueError,TypeError or other built-in error type.
  • Go: Returns a generic error.
  • .NET: Throws instances ofArgumentException,ArgumentNullException orsimilar built-in error type.

In most situations you should not explicitly handle programming errors. Instead,you should fix your code and configuration to avoid programming errors altogether.Consider the following Java snippet:

String uid = getUserInput();UserRecord user = FirebaseAuth.getInstance().getUser(uid);

If thegetUserInput() method returnsnull or empty strings, theFirebaseAuth.getUser() API throws anIllegalArgumentException. Instead ofexplicitly handling it, you can mitigate the issue by ensuring thegetUserInput() method never returns an invalid UID string. If that’s notpossible, implement the necessary argument checking in your own code as follows:

String uid = getUserInput();if (Strings.isNullOrEmpty(uid)) {    log.warn("UID must not be null or empty");    return;}UserRecord user = FirebaseAuth.getInstance().getUser(uid);

As a principle, never retry on programming errors. Allowing for fail-fastsemantics on programming errors is often the best course of action because itexposes programming bugs and configuration errors during development, where theycan be promptly fixed. Fail-fast in this context can mean letting the errorspropagate to a global error handler in your application, or just logging themfor audit purposes followed by the termination of the current execution flow(the application should not have to crash). In general, follow the errorhandling best practices of your programming language and the applicationframework. This alone is often sufficient to correctly deal with this class oferrors.

Typically, the bulk of your error handling efforts will focus on handlingAPIerrors. Some of these errors are recoverable, such as errors that resulted froma temporarily unavailable service, and some are even anticipated during thenormal program execution flow, such as detecting invalid or expired ID tokens.The rest of this guide outlines how the Admin SDK represents such API errors,and the various options that are available for handling them.

Structure of an API error

An API error consists of the following components:

  1. Error code
  2. Error message
  3. Service error code (Optional)
  4. HTTP response (Optional)

Every API error is guaranteed to contain an error code and an error message.Certain API errors also contain a service error code that is specific to the APIthat generated the error. For example some errors generated by the Firebase AuthAPI contain a service error code that is specific to Firebase Auth. If the errorwas the result of an HTTP error response from a backend service, the API erroralso contains the corresponding HTTP response. This can be used to inspect theexact headers and contents of the original response, which is useful fordebugging, logging, or implementing more sophisticated error handling logic.

All Admin SDK implementations except Node.js provide APIs that enable accessingthe above components of API errors.

Error types and APIs by language

Java

In Java all API errors extend theFirebaseException class. You can access theerror code, error message and the optional HTTP response from this base class.

publicclassFirebaseExceptionextendsException{@NonNullpublicErrorCodegetErrorCode(){//...}@NonNullpublicStringgetMessage(){//...}@NullablepublicIncomingHttpResponsegetHttpResponse(){//...}}

APIs that expose service error codes provide API-specific subclasses ofFirebaseException. For example all public methods in theFirebaseAuth APIare declared to throw instances ofFirebaseAuthException. You can access theservice error code from this derived class.

publicclassFirebaseAuthExceptionextendsFirebaseException{@NullablepublicAuthErrorCodegetAuthErrorCode(){//...}}

Python

In Python all API errors extend theexceptions.FirebaseErrorclass. You can access the error code, the error message, and the optional HTTPresponse from this base class.

classFirebaseError(Exception):@propertydefcode(self):#...@propertydefmessage(self):#...@propertydefhttp_response(self):#...

Moreover, Python Admin SDK offers separate derived classes for each error code.We refer to them asplatform error classes.

classInvalidArgumentError(FirebaseError):# ...classNotFoundError(FirebaseError):# ...

You can either catchFirebaseError in your code and check itscode, orperform anisinstance() check against a platform error class. Or you can writecode to directly catch specific platform error types. The latter approach islikely to result in more readable error handling code.

APIs that expose service error codes provide API-specific subclasses of platformerror classes. For example, all public methods in theauth module may throwAPI-specific error types such asauth.UserNotFoundError andauth.ExpiredIdTokenError.

classUserNotFoundError(exceptions.NotFoundError):# …classExpiredIdTokenError(exceptions.InvalidArgumentError):# ...

Go

The Go Admin SDK provides anerrorutils package which contains a series offunctions that allow testing for error codes.

packageerrorutilsfuncIsInvalidArgument(errerror)bool{//...}funcIsNotFound(errerror)bool{//...}

The error message is simply the string returned by theError() function of anerror. The optional HTTP response can be accessed by calling theerrorutils.HTTPResponse() function, which returns an*http.Response.

It is safe to passnil or any other error value to the error checkingfunctions in theerrorutils package. They returntrue if the input argumentactually contains the error code in question, and returnfalse for everythingelse. TheHTTPResponse() function has similar behavior, except it returnsnil instead offalse.

APIs that expose service error codes provide API-specific error checkingfunctions in the corresponding packages. For example, theauth packageprovides the functionsIsUserNotFound() andIsExpiredIDTokenError().

.NET

In .NET all API errors extend theFirebaseExceptionclass. You can access theplatform error code, error message and the optional HTTP response from this baseclass.

public class FirebaseException : Exception {    public ErrorCode ErrorCode { get; }    public String Message { get; }    public HttpResponseMessage HttpResponse { get; }}

APIs that expose service error codes provide API-specific subclasses ofFirebaseException. For example, all public methods in theFirebaseAuth APIare declared to throw instances ofFirebaseAuthException.You can access theservice error code from this derived class.

public class FirebaseAuthException : FirebaseException {    public AuthErrorCode AuthErrorCode { get; }}

Platform error codes

Error codes are common across all Firebase and Google Cloud Platform services.The following table outlines all the possible platform error codes. This is astable list, and is expected to remain unchanged for a long period.

INVALID_ARGUMENTClient specified an invalid argument.
FAILED_PRECONDITIONRequest cannot be executed in the current system state, such as deleting a non-empty directory.
OUT_OF_RANGEClient specified an invalid range.
UNAUTHENTICATEDRequest not authenticated due to missing, invalid or expired OAuth token.
PERMISSION_DENIEDClient does not have sufficient permission. This can happen because the OAuth token does not have the right scopes, the client does not have permission, or the API has not been enabled for the client project.
NOT_FOUNDSpecified resource not found, or the request is rejected due to undisclosed reasons such as whitelisting.
CONFLICTConcurrency conflict, such as read-modify-write conflict. Only used by a few legacy services. Most services use ABORTED or ALREADY_EXISTS instead of this. Refer to the service-specific documentation to see which one to handle in your code.
ABORTEDConcurrency conflict, such as read-modify-write conflict.
ALREADY_EXISTSThe resource that a client tried to create already exists.
RESOURCE_EXHAUSTEDEither out of resource quota or reaching rate limiting.
CANCELLEDRequest cancelled by the client.
DATA_LOSSUnrecoverable data loss or data corruption. The client should report the error to the user.
UNKNOWNUnknown server error. Typically a server bug.

This error code is also assigned to local response parsing (unmarshal) errors, and a wide range of other low-level I/O errors that are not easily diagnosable.

INTERNALInternal server error. Typically a server bug.
UNAVAILABLEService unavailable. Typically the server is temporarily down.

This error code is also assigned to local network errors (connection refused, no route to host).

DEADLINE_EXCEEDEDRequest deadline exceeded. This will happen only if the caller sets a deadline that is shorter than the target API’s default deadline (i.e. requested deadline is not enough for the server to process the request), and the request did not finish within the deadline.

This error code is also assigned to local connection and read timeouts.

Most APIs can only result in a subset of the above error codes. In any case, youare not expected to explicitly handle all these error codes whenimplementing your error handlers. Most applications would only be interested in1-2 specific error codes and treat everything else as a generic, unrecoverablefailure.

Service-specific error codes

Firebase Auth

CERTIFICATE_FETCH_FAILEDFailed to fetch public key certificates required to verify a JWT (ID token or session cookie).
EMAIL_ALREADY_EXISTSA user already exists with the provided email.
EXPIRED_ID_TOKENThe ID token specified toverifyIdToken() is expired.
EXPIRED_SESSION_COOKIEThe session cookie specified toverifySessionCookie() iis expired.
INVALID_DYNAMIC_LINK_DOMAINThe provided dynamic link domain is not configured or authorized for the current project. Related to email action link APIs.
INVALID_ID_TOKENThe ID token specified toverifyIdToken() is invalid.
INVALID_SESSION_COOKIEThe session cookie specified toverifySessionCookie() is invalid.
PHONE_NUMBER_ALREADY_EXISTSA user already exists with the provided phone number.
REVOKED_ID_TOKENThe ID token specified toverifyIdToken() is revoked.
REVOKED_SESSION_COOKIEThe session cookie specified toverifySessionCookie() is expired.
UNAUTHORIZED_CONTINUE_URLThe domain of the continue URL is not whitelisted. Related to email action link APIs.
USER_NOT_FOUNDNo user record found for the given identifier.

Firebase Cloud Messaging

THIRD_PARTY_AUTH_ERRORAPNs certificate or web push auth API key was invalid or missing.
INVALID_ARGUMENTOne or more arguments specified in the request were invalid.
INTERNALInternal server error.
QUOTA_EXCEEDEDSending limit exceeded for the message target.
SENDER_ID_MISMATCHThe authenticated sender ID is different from the sender ID for the registration token. This usually means the sender and the target registration token are not in the same Firebase project.
UNAVAILABLECloud Messaging service is temporarily unavailable.
UNREGISTEREDApp instance was unregistered from FCM. This usually means that the device registration token used is no longer valid and a new one must be used.

Automatic retries

The Admin SDK automatically retries certain errors before exposing those errorsto the users. In general, following types of errors are transparently retried:

  • All API errors resulting from HTTP 503 (Service Unavailable) responses.
  • Some API errors resulting from HTTP 500 (Internal Server Error) responses.
  • Most low-level I/O errors (connection refused, connection reset etc).

The SDK will retry each of the above errors up to 5 times (the original attempt+ 4 retries) with exponential backoff. You can implement your own retrymechanisms at the application level if you want, but this is typically notrequired.

Retry-After support

The Go and .NET implementations of the Admin SDK come with support forhandling the HTTPRetry-After header. That is, if the error response sent bythe backend servers contain the standardRetry-After header, the SDK willrespect that when retrying as long as the specified wait duration is not verylong. If theRetry-After header indicates a very long wait duration, the SDKwill bypass retries and throw the appropriate API error.

The Python Admin SDK does not currently support theRetry-After header, andonly supports simple exponential backoff.

API error handling examples

Implementing a generic error handler

In most cases what you want is a generic error handler that catches a broadrange of errors to prevent unexpected termination of the program flow due to anAPI error. Such error handlers usually just log the errors for audit purposes,or invoke some other default error handling routine for all encountered APIerrors. They are not necessarily interested in the different error codes or thereasons that may have caused the error.

Java

try{FirebaseTokentoken=FirebaseAuth.getInstance().verifyIdToken(idToken);performPrivilegedOperation(token.getUid());}catch(FirebaseAuthExceptionex){System.err.println("Failed to verify ID token: "+ex.getMessage());}

Python

try:token=auth.verify_id_token(idToken)perform_privileged_pperation(token.uid)exceptexceptions.FirebaseErrorasex:print(f'Failed to verify ID token:{ex}')

Go

token,err:=client.VerifyIDToken(ctx,idToken)iferr!=nil{log.Printf("Failed to verify ID token: %v",err)return}performPrivilegedOperation(token)

.Net

try{vartoken=awaitFirebaseAuth.DefaultInstance.VerifyIdTokenAsync(idToken);PerformPrivilegedOperation(token.getUid());}catch(FirebaseAuthExceptionex){Conole.WriteLine($"Failed to verify ID token: {ex.Message}");}

Checking error codes

In some cases, you would want to inspect the exact error codes, and invokedifferent context-aware error handling routines. In the following example, wehave an error handler that logs more specific error messages based on theservice error code.

Java

try{FirebaseTokentoken=FirebaseAuth.getInstance().verifyIdToken(idToken);performPrivilegedOperation(token.getUid());}catch(FirebaseAuthExceptionex){if(ex.getAuthErrorCode()==AuthErrorCode.ID_TOKEN_EXPIRED){System.err.println("ID token has expired");}elseif(ex.getAuthErrorCode()==AuthErrorCode.ID_TOKEN_INVALID){System.err.println("ID token is malformed or invalid");}else{System.err.println("Failed to verify ID token: "+ex.getMessage());}}

Python

try:token=auth.verify_id_token(idToken)perform_privileged_operation(token.uid)exceptauth.ExpiredIdTokenError:print('ID token has expired')exceptauth.InvalidIdTokenError:print('ID token is malformed or invalid')exceptexceptions.FirebaseErrorasex:print(f'Failed to verify ID token:{ex}')

Go

token,err:=client.VerifyIDToken(ctx,idToken)ifauth.IsIDTokenExpired(err){log.Print("ID token has expired")return}ifauth.IsIDTokenInvalid(err){log.Print("ID token is malformed or invalid")return}iferr!=nil{log.Printf("Failed to verify ID token: %v",err)return}performPrivilegedOperation(token)

.Net

try{vartoken=awaitFirebaseAuth.DefaultInstance.VerifyIdTokenAsync(idToken);PerformPrivilegedOperation(token.getUid());}catch(FirebaseAuthExceptionex){if(ex.AuthErrorCode==AuthErrorCode.ExpiredIdToken){Console.WriteLine("ID token has expired");}elseif(ex.AuthErrorCode==AuthErrorCode.InvalidIdToken){Console.WriteLine("ID token is malformed or invalid");}else{Conole.WriteLine($"Failed to verify ID token: {ex.Message}");}}

Here’s another example where we check for both top-level and service error codes:

Java

try{FirebaseMessaging.getInstance().send(createMyMessage());}catch(FirebaseMessagingExceptionex){if(ex.getMessagingErrorCode()==MessagingErrorCode.UNREGISTERED){System.err.println("App instance has been unregistered");removeTokenFromDatabase();}elseif(ex.getErrorCode()==ErrorCode.Unavailable){System.err.println("FCM service is temporarily unavailable");scheduleForRetryInAnHour();}else{System.err.println("Failed to send notification: "+ex.getMessage());}}

Python

try:messaging.send(create_my_message())exceptmessaging.UnregisteredError:print('App instance has been unregistered')remove_token_from_database()exceptexceptions.UnavailableError:print('FCM service is temporarily unavailable')schedule_for_retry_in_an_hour()exceptexceptions.FirebaseErrorasex:print(f'Failed to send notification:{ex}')

Go

_,err:=client.Send(ctx,createMyMessage())ifmessaging.IsUnregistered(err){log.Print("App instance has been unregistered")removeTokenFromDatabase()return}iferrorutils.IsUnavailable(err){log.Print("FCM service is temporarily unavailable")scheduleForRetryInAnHour()return}iferr!=nil{log.Printf("Failed to send notification: %v",err)return}

.Net

try{awaitFirebaseMessaging.DefaultInstance.SendAsync(createMyMessage());}catch(FirebaseMessagingExceptionex){if(ex.MessagingErrorCode==MessagingErrorCode.UNREGISTERED){Console.WriteLine("App instance has been unregistered");removeTokenFromDatabase();}elseif(ex.ErrorCode==ErrorCode.Unavailable){Console.WriteLine("FCM service is temporarily unavailable");scheduleForRetryInAnHour();}else{Console.WriteLine($"Failed to send notification: {ex.Message}");}}

Accessing the HTTP response

In some rare cases you may want to inspect the HTTP error response returned bya backend service and perform some error handling action on it. The Admin SDKexposes both the headers and the contents of these error responses. The responsecontent is usually returned as a string or a raw byte sequence, and can beparsed into any target format necessary.

Java

try{FirebaseMessaging.getInstance().send(createMyMessage());}catch(FirebaseMessagingExceptionex){IncomingHttpResponseresponse=ex.getHttpResponse();if(response!=null){System.err.println("FCM service responded with HTTP "+response.getStatusCode());Map<String,Object>headers=response.getHeaders();for(Map.Entry<String,Object>entry:headers.entrySet()){System.err.println(">>> "+entry.getKey()+": "+entry.getValue());}System.err.println(">>>");System.err.println(">>> "+response.getContent());}}

Python

try:messaging.send(create_my_message())exceptexceptions.FirebaseErrorasex:response=ex.http_responseifresponseisnotNone:print(f'FCM service responded with HTTP{response.status_code}')forkey,valueinresponse.headers.items():print(f'>>>{key}:{value}')print('>>>')print(f'>>>{response.content}')

Go

_,err:=client.Send(ctx,createMyMessage())ifresp:=errorutils.HTTPResponse(err);resp!=nil{log.Printf("FCM service responded with HTTP %d",resp.StatusCode)forkey,value:=rangeresp.Header{log.Printf(">>> %s: %v",key,value)}deferresp.Body.Close()b,_:=ioutil.ReadAll(resp.Body)log.Print(">>>")log.Printf(">>> %s",string(b))return}

.Net

try{awaitFirebaseMessaging.DefaultInstance.SendAsync(createMyMessage());}catch(FirebaseMessagingExceptionex){varresponse=ex.HttpResponseifresponse!=null{Console.WriteLine($"FCM service responded with HTTP { response.StatusCode}");varheaders=response.Headers;for(varentryinresponse.Headers){Console.WriteLine($">>> {entry.Key}: {entry.Value}");}varbody=awaitresponse.Content.ReadAsString();Console.WriteLine(">>>");Console.WriteLine($">>> {body}");}}

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-11-25 UTC.