How to catch a Firebase Auth specific exceptions

60,322

Solution 1

You can throw the Exception returned by task.getException inside a try block and catch each type of Exception that may be thrown by the method you are using.

Here is an example from the OnCompleteListener for the createUserWithEmailAndPassword method.

if(!task.isSuccessful()) {
    try {
        throw task.getException();
    } catch(FirebaseAuthWeakPasswordException e) {
        mTxtPassword.setError(getString(R.string.error_weak_password));
        mTxtPassword.requestFocus();
    } catch(FirebaseAuthInvalidCredentialsException e) {
        mTxtEmail.setError(getString(R.string.error_invalid_email));
        mTxtEmail.requestFocus();
    } catch(FirebaseAuthUserCollisionException e) {
        mTxtEmail.setError(getString(R.string.error_user_exists));
        mTxtEmail.requestFocus();
    } catch(Exception e) {
        Log.e(TAG, e.getMessage());
    }
}

Solution 2

In addition to @pdegand59 answer, I found some error code in Firebase library and test on Android (the returned error code). Hope this helps, Regards.

 ("ERROR_INVALID_CUSTOM_TOKEN", "The custom token format is incorrect. Please check the documentation."));
 ("ERROR_CUSTOM_TOKEN_MISMATCH", "The custom token corresponds to a different audience."));
 ("ERROR_INVALID_CREDENTIAL", "The supplied auth credential is malformed or has expired."));
 ("ERROR_INVALID_EMAIL", "The email address is badly formatted."));
 ("ERROR_WRONG_PASSWORD", "The password is invalid or the user does not have a password."));
 ("ERROR_USER_MISMATCH", "The supplied credentials do not correspond to the previously signed in user."));
 ("ERROR_REQUIRES_RECENT_LOGIN", "This operation is sensitive and requires recent authentication. Log in again before retrying this request."));
 ("ERROR_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL", "An account already exists with the same email address but different sign-in credentials. Sign in using a provider associated with this email address."));
 ("ERROR_EMAIL_ALREADY_IN_USE", "The email address is already in use by another account."));
 ("ERROR_CREDENTIAL_ALREADY_IN_USE", "This credential is already associated with a different user account."));
 ("ERROR_USER_DISABLED", "The user account has been disabled by an administrator."));
 ("ERROR_USER_TOKEN_EXPIRED", "The user\'s credential is no longer valid. The user must sign in again."));
 ("ERROR_USER_NOT_FOUND", "There is no user record corresponding to this identifier. The user may have been deleted."));
 ("ERROR_INVALID_USER_TOKEN", "The user\'s credential is no longer valid. The user must sign in again."));
 ("ERROR_OPERATION_NOT_ALLOWED", "This operation is not allowed. You must enable this service in the console."));
 ("ERROR_WEAK_PASSWORD", "The given password is invalid."));
 ("ERROR_MISSING_EMAIL", "An email address must be provided.";

Solution 3

There are a number of exceptions associated with firebase auth. In addition to @kingspeech

You should use ((FirebaseAuthException)task.getException()).getErrorCode() to get the type of error and then handle it in switch like this :

private void loginUser(String email, String password) {

        mAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener(new OnCompleteListener<AuthResult>() {

            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {

                if (task.isSuccessful()) {

                    startActivity(new Intent(MainActivity.this, Main2Activity.class));

                } else {

                    String errorCode = ((FirebaseAuthException) task.getException()).getErrorCode();

                    switch (errorCode) {

                        case "ERROR_INVALID_CUSTOM_TOKEN":
                            Toast.makeText(MainActivity.this, "The custom token format is incorrect. Please check the documentation.", Toast.LENGTH_LONG).show();
                            break;

                        case "ERROR_CUSTOM_TOKEN_MISMATCH":
                            Toast.makeText(MainActivity.this, "The custom token corresponds to a different audience.", Toast.LENGTH_LONG).show();
                            break;

                        case "ERROR_INVALID_CREDENTIAL":
                            Toast.makeText(MainActivity.this, "The supplied auth credential is malformed or has expired.", Toast.LENGTH_LONG).show();
                            break;

                        case "ERROR_INVALID_EMAIL":
                            Toast.makeText(MainActivity.this, "The email address is badly formatted.", Toast.LENGTH_LONG).show();
                            etEmail.setError("The email address is badly formatted.");
                            etEmail.requestFocus();
                            break;

                        case "ERROR_WRONG_PASSWORD":
                            Toast.makeText(MainActivity.this, "The password is invalid or the user does not have a password.", Toast.LENGTH_LONG).show();
                            etPassword.setError("password is incorrect ");
                            etPassword.requestFocus();
                            etPassword.setText("");
                            break;

                        case "ERROR_USER_MISMATCH":
                            Toast.makeText(MainActivity.this, "The supplied credentials do not correspond to the previously signed in user.", Toast.LENGTH_LONG).show();
                            break;

                        case "ERROR_REQUIRES_RECENT_LOGIN":
                            Toast.makeText(MainActivity.this, "This operation is sensitive and requires recent authentication. Log in again before retrying this request.", Toast.LENGTH_LONG).show();
                            break;

                        case "ERROR_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL":
                            Toast.makeText(MainActivity.this, "An account already exists with the same email address but different sign-in credentials. Sign in using a provider associated with this email address.", Toast.LENGTH_LONG).show();
                            break;

                        case "ERROR_EMAIL_ALREADY_IN_USE":
                            Toast.makeText(MainActivity.this, "The email address is already in use by another account.   ", Toast.LENGTH_LONG).show();
                            etEmail.setError("The email address is already in use by another account.");
                            etEmail.requestFocus();
                            break;

                        case "ERROR_CREDENTIAL_ALREADY_IN_USE":
                            Toast.makeText(MainActivity.this, "This credential is already associated with a different user account.", Toast.LENGTH_LONG).show();
                            break;

                        case "ERROR_USER_DISABLED":
                            Toast.makeText(MainActivity.this, "The user account has been disabled by an administrator.", Toast.LENGTH_LONG).show();
                            break;

                        case "ERROR_USER_TOKEN_EXPIRED":
                            Toast.makeText(MainActivity.this, "The user\\'s credential is no longer valid. The user must sign in again.", Toast.LENGTH_LONG).show();
                            break;

                        case "ERROR_USER_NOT_FOUND":
                            Toast.makeText(MainActivity.this, "There is no user record corresponding to this identifier. The user may have been deleted.", Toast.LENGTH_LONG).show();
                            break;

                        case "ERROR_INVALID_USER_TOKEN":
                            Toast.makeText(MainActivity.this, "The user\\'s credential is no longer valid. The user must sign in again.", Toast.LENGTH_LONG).show();
                            break;

                        case "ERROR_OPERATION_NOT_ALLOWED":
                            Toast.makeText(MainActivity.this, "This operation is not allowed. You must enable this service in the console.", Toast.LENGTH_LONG).show();
                            break;

                        case "ERROR_WEAK_PASSWORD":
                            Toast.makeText(MainActivity.this, "The given password is invalid.", Toast.LENGTH_LONG).show();
                            etPassword.setError("The password is invalid it must 6 characters at least");
                            etPassword.requestFocus();
                            break;

                    }
                }
            }
        });
    }

Solution 4

You should use ((FirebaseAuthException)task.getException()).getErrorCode() to get the type of error and fail gracefully if this is the error code for a bad formatted email.

Unfortunately, I couldn't find the list of error codes used by Firebase. Trigger the exception once, note the error code and code accordingly.

Solution 5

If you simply want display a message to the user this works. Simple and Elegant:

if (!task.isSuccessful()) {
    Log.w(TAG, "signInWithEmail:failed", task.getException());
    Toast.makeText(LoginActivity.this, "User Authentication Failed: " + task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}

It appears that the .getMessage() method converts the exception to a usable format for us already and all we have to do is display that somewhere to the user.

(This is my first comment, constructive criticism please)

Share:
60,322
Relm
Author by

Relm

Updated on July 09, 2022

Comments

  • Relm
    Relm almost 2 years

    Using Firebase, how do I catch a specific exception and tell the user gracefully about it? E.g :

    FirebaseAuthInvalidCredentialsException: The email address is badly formatted.

    I'm using the code below to signup the user using email and password, but I'm not that advanced in java.

    mAuth.createUserWithEmailAndPassword(email, pwd)
        .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
    
        @Override
        public void onComplete(@NonNull Task<AuthResult> task) {
            if (!task.isSuccessful()) {
                //H.toast(c, task.getException().getMessage());
                Log.e("Signup Error", "onCancelled", task.getException());
            } else {
                FirebaseUser user = mAuth.getCurrentUser();
                String uid = user.getUid();
            }
        }    
    });
    
  • alzee
    alzee almost 8 years
    This does not actually answer his question.
  • Itzdsp
    Itzdsp almost 8 years
    This is for Auth Specific right, two more exceptions are missing. Check the reference
  • alzee
    alzee almost 8 years
    He asked "how do I catch a specific exception and tell the user gracefully about it" not "give me a list of exceptions that are possible". Your answer does not help with either of those things -- how to catch the exception, or how to inform the user about it.
  • Cocorico
    Cocorico about 7 years
    I have an issue with this. Firebase just return to me a FirebaseException, not a FirebaseAuthWeakPasswordException or other. but the message seems to be good : "WEAK_PASSWORD". Any idea ?
  • Steve Guidetti
    Steve Guidetti about 7 years
    You can check the message in the final catch block for any exceptions that don't have a specific type.
  • Cocorico
    Cocorico about 7 years
    Yes, I see it. But why do you have FirebaseAuthWeakPasswordException and I can't ? And it's bad code if I do a switch case with msg type when I should be able to do it properly with class type.
  • Steve Guidetti
    Steve Guidetti about 7 years
    I found the Firebase framework to be inconsistent about the types of exceptions it throws. I had to check the message in some methods because of that. It is messier but you have to work with what you get. I did file a bug report but I don't think anything came of that.
  • David Heisnam
    David Heisnam over 6 years
    task.getException() cannot always be cast to FirebaseAuthException, for instance when there is no network connectivity. In that case the Exception is FirebaseNetworkException
  • mehmet
    mehmet over 6 years
    @DavidH if you use task.getException() is not null, it will fix that problem
  • Taslim Oseni
    Taslim Oseni about 6 years
    Isn' this a little cumbersome?.. Compared to the other methods.
  • Kewal Shah
    Kewal Shah almost 6 years
    This gives a warning in the getMessage() method saying : Method invocation 'getMessage' may produce 'java.lang.NullPointerException'. How to resolve this?
  • Admin
    Admin almost 6 years
    It's telling you that getException() can return null so you could add... if(task.getException != null) { Toast.makeText... };
  • ninbit
    ninbit over 5 years
    @mehmet no, it will not fix the problem since task.getException() is not null when it is FirebaseNetworkException
  • chb
    chb about 5 years
    Hi, welcome to Stack Overflow. When answering a question that already has many answers, please be sure to add some additional insight into why the response you're providing is substantive and not simply echoing what's already been vetted by the original poster. This is especially important in "code-only" answers such as the one you've provided.