Running transaction in an onDelete() cloud function is causing Error: Could not load the default credentials

2,285 views
Skip to first unread message

Brian Begun

unread,
Oct 31, 2019, 10:42:53 PM10/31/19
to Firebase Google Group
Not understanding why this is happening.  I have several other cloud functions that run without issue.  I even have one that sets a customAuthToken and it runs without error.
The only difference with this one is that I'm using a firestore transaction.  Since I'm running this as a cloud function I'm using the default credentials, which to my understanding is acceptable for cloud functions, so I'm not sure why it's yelling at me.

Any help would be greatly appreciated.

Here's an abbreviated version of my function:

export = module.exports = functions.firestore
    .document('rootPath/{topDocID}/subcollection/{endDocID}')
    .onCreate(async (snap, context) => {
        const groupDocRef = admin.firestore().collection('rootPath').doc(context.params.topDocID);
        const transaction = admin.firestore().runTransaction(t => {
            return t.get(groupDocRef)
                .then(doc => {
                    const newAdminCount = doc.data().adminCount + 1;
                    t.update(groupDocRef, { adminCount: newAdminCount });
                    if (newAdminCount === 1) {
                        //set claim to role = "admin"
                        admin.auth().setCustomUserClaims(context.params.endDocID, { role: "admin" })
                            .then(() => {
                                console.log("Role set to: admin");
                            }).catch(error => {
                                console.log("Error.  Role failed to get set: ", error);
                            });
                    }
                    else {
                        console.log("Error.  No role set.  Invalid adminCount.");
                    }
                });
        }).then(result => {
            console.log('Transaction success', result);
        }).catch(error => {
            console.log('Transaction failure:', error);
        });
        return Promise.resolve();
    });

The error I'm getting specifically is:

Transaction failure: Error: Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.
    at GoogleAuth.getApplicationDefaultAsync (/srv/node_modules/google-auth-library/build/src/auth/googleauth.js:161:19)
    at <anonymous>
    at process._tickDomainCallback (internal/process/next_tick.js:229:7)


Sam Stern

unread,
Nov 1, 2019, 1:06:34 PM11/1/19
to Firebase Google Group
Hey Brian,

I ran the exact code you provided (except I changed it to onDelete since I think that's what you meant) and I had the exact same issue, so thanks for the simple reproduction!  Now I will try and figure out what's going on.

- Sam

--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/11f68efc-37b9-4606-9dd1-9c1eceb07324%40googlegroups.com.

Sam Stern

unread,
Nov 1, 2019, 1:20:39 PM11/1/19
to Firebase Google Group
Ok interestingly this only happened to me once:
Screenshot from 2019-11-01 10-15-14.png

Future calls resulted in success:
Screenshot from 2019-11-01 10-15-26.png

However the log order looked strange to me so I think this might be a race condition because we are not returning the transaction!  So where you have:

        const transaction = admin.firestore().runTransaction(t => {
            // ...
        }).then(result => {
            // ...
        }).catch(error => {
            // ...
        });
        return Promise.resolve();


What you want to do is return the main chain and get rid of the Promise.resolve() at the end:

        return admin.firestore().runTransaction(t => {
            // ...
        }).then(result => {
            // ...
        }).catch(error => {
            // ...
        });

This is still just a guess, but I am sure that returning the transaction is more correct anyway.  Let me know if that helps you!

- Sam

Brian Begun

unread,
Nov 1, 2019, 5:25:34 PM11/1/19
to Firebase Google Group
Hi Sam,
          okay, great news.  It looks like that was the problem.  I can run it consistently now with success.  One thing to note:  I used the transaction example from the google docs (under Node.js), so it might be worth updating the example to have the proper return.  

Here's the Google doc example:

let transaction = db.runTransaction(t => {
  return t.get(cityRef)
   
.then(doc => {
     
// Add one person to the city population.
     
// Note: this could be done without a transaction
     
//       by updating the population using FieldValue.increment()
      let newPopulation
= doc.data().population + 1;
      t
.update(cityRef, {population: newPopulation});
   
});
}).then(result => {
  console
.log('Transaction success!');
}).catch(err => {
  console
.log('Transaction failure:', err);
});

Here's the link for your convenience:
https://firebase.google.com/docs/firestore/manage-data/transactions

Thanks again for the help!

Best,
     Brian

Sam Stern

unread,
Nov 1, 2019, 5:36:43 PM11/1/19
to Firebase Google Group
Glad it worked out for you!  Otherwise I had no more guesses haha.  I think the docs are still correct because you don't always need to return the result of the runTransaction chain, only when that's the main operation of a Cloud Function.  But I can see how it was confusing and will think about if there's a way to clarify that.

- Sam

--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.

Brian Begun

unread,
Nov 2, 2019, 7:06:17 AM11/2/19
to Firebase Google Group
Any clarity to the docs regarding this would be greatly appreciated.

Thanks!
To unsubscribe from this group and stop receiving emails from it, send an email to fireba...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages