node.jsfirebasegoogle-cloud-functions

How to throw an error on a Firebase callable cloud function?


I'm trying to create a new user on Firebase using a callable cloud function. Whenever there is an error (eg: the email is invalid) the function always returns the same cryptic error to my Firebase app no matter what I do:

{"error":{"status":"INTERNAL","message":"INTERNAL"}}

In the Firebase console I also get this:

Unhandled error Error: Unknown error status: auth/invalid-email

Which doesn't make much sense since I am actually handling the error. This is the code of the cloud function:

exports.createUser = (data, context) => {
    return admin.auth().createUser({
        email: data.email,
        password: data.password
    }).catch((error) => {
        throw new functions.https.HttpsError(error.errorInfo.code, error.errorInfo.message);
    });
}

As shown I've tried to use throw functions.https.HttpsError which is what the documentation suggests.

I've also tried return functions.https.HttpsError or even throwing my own error with the same result.

I've used try/catch with await instead of using then() and catch(). Same result. The functions console still informs me that the error is not handled which is absurd.

So how can I throw a proper error to my users when using a callable cloud function?


Solution

  • It looks like you're trying to pass along the error code from the Admin SDK verbatim, but that's not a valid strategy. Read the documentation carefully - it's sending you to the API documentation for HttpsError to find the list of error codes that are valid to send. The code property links to FunctionsErrorCode which shows the list of valid codes:

    "ok" | "cancelled" | "unknown" | "invalid-argument" | "deadline-exceeded" | "not-found" | "already-exists" | "permission-denied" | "resource-exhausted" | "failed-precondition" | "aborted" | "out-of-range" | "unimplemented" | "internal" | "unavailable" | "data-loss" | "unauthenticated"

    The Admin SDK is giving you "auth/invalid-email", which is not valid here. You're going to have to translate that into one of the valid codes. Perhaps "invalid-argument" might be appropriate. That's going to get translated further into a numerical HTTP response code, which you will receive on the client.