how to solve Your function was killed because it raised an unhandled error in my Firebase emulator?

Viewed 1308

I am trying to run the Firestore trigger code below using Firebase emulators, firebase emulators:start

as you can see, inside the firestore trigger, I have a code to delete an image stored in Firebase Storage

my code:

exports.onDelete = functions
.firestore.document(path)
.onDelete((snapshot, context) => {

    try {

        const deletedUser = new User(snapshot.data());
        const promise1 = db.doc(`devices/${deletedUser.uid}`).delete();

        // deleting the image in Storage
        const defaultBucket = storage.bucket();
        const profilePictureFile = defaultBucket.file(`profilePicture/${deletedUser.uid}`);
        const promise2 = profilePictureFile.delete();

        const promises: Promise<any>[] = [promise1, promise2];
        return Promise.all(promises);

    } catch (error) {
        console.log(error);
        return Promise.reject(error);
    }
    

});

because Firebase emulators currently doesn't have emulator for storage, so I expect there will be an error.

but I have a warning like this

enter image description here

as you can see at the very bottom, there is a warning that say

Your function was killed because it raised an unhandled error.

is this a serious error? I mean, I think I already provide the try catch block in my code, but why it is still considered as an unhandled error? how to solve this?

sorry, I am a beginner in Node, I am a mobile developer. so I am sorry if my question is a bit silly

3 Answers

When you don't catch errors generated from Promises, that's considered an unhandled error. It looks like you're trying to delete an object that doesn't exist, so it's throwing an error that you're not catching in the Promise.all call.

To fix your code without changing it substantially, just add a .catch() to your Promise.all() call.

Promise.all(promises)
  .catch(() => console.error("Oh no, an error occurred!"));

Simply put, a promise should always have at least one of these functions attached: .then(), .catch() or .finally()

Bad

myFunction.doSomethingReturnPromise();

Good

myFunction.doSomethingReturnPromise().then();

Another important point is that Promise.all() is all-or-nothing, meaning if one promise fails it exits immediately. You should instead run each promise individually if there's a chance that the file doesn't exist otherwise you need to create wrapper functions to delete files that always resolve.

Also don't wrap all of your code in a try/catch, instead handle each action individually. However I'm assuming you don't actually care if it succeeds or not, correct?

Here's how I would write this function:

/**
 * Generic delete funcion that will call .delete() on storage objects or database nodes
 * @param doc
 */
const deleteObj = (doc) => {
    return new Promise((resolve: null) => {
        // Delete and resolve no matter what
        doc.delete()
            .finally(() => resolve());
    });
};

exports.onDelete = functions.firestore.document(path).onDelete((snapshot, context) => {
    const deletedUser = new User(snapshot.data());
    const defaultBucket = storage.bucket();

    // Since both types of objects have a similarly named .delete() function, we can use the same function
    // to delete them
    const promises = [
        deleteObj(db.doc(`devices/${deletedUser.uid}`)),
        deleteObj(defaultBucket.file(`profilePicture/${deletedUser.uid}`))
    ];

    Promise.all(promises)
      .finally(() => console.log("All done"));
});

Note: In my revised code, since all of the promises given to Promise.all() are guaranteed to resolve, I don't need to add a .catch() or wrap it in try/catch.

I was facing the same issue. In my case, I just updated the firebase CLI using the below command.It worked for me.

npm install -g firebase-tools

i also faced same issue but with async/await format using try/catch. i also cant figure out until i restarted my emulator and the error magically disappeared.

Related