Firebase Functions: Could not load default credentials - firebase

I have a Firebase Function that subscribes to a Cloud PubSub topic. App is initialized very simply like this:
import * as admin from 'firebase-admin';
admin.initializeApp();
I'm getting this error:
"Error: Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.
at GoogleAuth.getApplicationDefaultAsync (/srv/functions/node_modules/google-auth-library/build/src/auth/googleauth.js:161:19)
at process._tickCallback (internal/process/next_tick.js:68:7)"
Here's the weird thing. It typically works. In other words, if I trigger it a second time it works. And a third time. Most often it seems to fail the first time it runs after a new firebase deploy and possibly on a "cold start."
Not sure what I'm doing wrong and why it would fail only on the first run.

SOLVED! This answer helped:
Error: Could not load the default credentials (Firebase function to firestore)
From within a Firebase Function for an API call, I was publishing to a Cloud PubSub topic like this:
pubsub.topic(topicName).publish(dataBuffer, customAttributes)
I was not awaiting the response and was immediately sending the 2XX HTTP response back to the client. The execution seemed to continue fine, but obviously it did not behave as intended.
Sometimes the API response call itself would fail (and never publish the message), but sometimes not. In other cases, the publish would succeed but the Firebase Function subscribing to the topic would fail!
In all cases, this seemed to resolve itself after running the script a second time. For this reason, I still believe it had something to do with a cold start.
But since I changed it to await like this:
await pubsub.topic(topicName).publish(dataBuffer, customAttributes)
I have not seen this problem happen again.

Related

How to continue running Firebase Cloud Function after request is finished

Really bizarre that Firebase doesn't seem to work quite like typical Express app. Whatever I write in Express and copy-paste to Firebase Functions I typically get error. There is one that I can't figure out on my own though.
This endpoint is designed to start a function and live long enough to finish even longer task. That request is a webhook (send docs, we will transform them and ping you when it's done to specified another webhook). Very simplified example below:
router.post('/', (req, res) => {
try {
generateZipWithDocuments(data) // on purpose it's not async so request can return freely
res.sendStatus(201)
} catch (error) {
res.send({ error })
}
})
On my local machine it works (both pure Express app and locally emulated Firebase Functions), but in the cloud it has problems and even though I put a cavalcade of console.log() I don't get much information. No error from Firebase.
If generateZipWithDocuments() is not asynchronous res.sendStatus() will be immediately executed after it, and the Cloud Function will be terminated (and the job done by generateZipWithDocuments() will not be completed). See the doc here for more details.
You have two possibilities:
You make it asynchronous and you wait its job is completed before sending the response. You would typically use async/await for that. Note that the maximum execution time for a Cloud Function is 9 minutes.
You delegate the long time execution job to another Cloud Function and, then, you send the response. For delegating the job to another Cloud Function, you should use Pub/Sub. See Pub/Sub triggers, the sample quickstart, and this SO thread for more details on how to implement that. In the Pub/Sub triggered Function, when the job is done you can inform the user via an email, a notification, the update of a Firestore document on which you have set a listener, etc... If generateZipWithDocuments() takes a long time, it is clearly the most user friendly option.

Permission errors unit-testing Google Cloud Functions calling firestore db

I'm following the guide at https://firebase.google.com/docs/functions/unit-testing, but I always get " FirebaseError: Missing or insufficient permissions" when I run my test. I have the correct service-account.json file and I'm setting up firebase-functions-test with it (that part goes without error).
I've tried it with the emulator running (setting the FIRESTORE_EMULATOR_HOST var), and without it (which I assume uses live data) but I always get this error, as soon as my code under test does a db request such as:
data = await db().collection('/machines').get()
So my function under test is getting called, but it just can't do anything.
I also tried calling firebase.initializeApp() the same way I do in my front-end app, but that doesn't help, although without it I get the error telling me to call Firebase App.initializeApp().
firebase use is set to my current project.
I also tried running my test as firebase emulators:exec jest, no difference.
Any ideas?

Why do I get "Client is not yet ready to issue requests" - Firestore get() fails when called by Schedule function

In my Firebase project I have a functions.pubsub.schedule().onRun() that runs every 5 minutes to perform some calendar related tasks. It needs to look up in my Firestore collections and does so with a .get() query.
This has been working fine until sometime 2020-03-13 in the morning where the function started to throw
2020-03-13 09:36:02.326 CET scheduledHooks 1042277797598294
Error: INTERNAL ERROR: Client is not yet ready to issue requests.
at Firestore.get projectId [as projectId] (/srv/functions/node_modules/#google-cloud/firestore/build/src/index.js:401:19)
at Query.toProto (/srv/functions/node_modules/#google-cloud/firestore/build/src/reference.js:1556:42) at Query._get (/srv/functions/node_modules/#google-cloud/firestore/build/src/reference.js:1466:30)
at Query.get (/srv/functions/node_modules/#google-cloud/firestore/build/src/reference.js:1457:21)
at FirebaseActivitiesCollection.<anonymous> (/srv/functions/lib/collections/activities/FirebaseActivitiesCollection.js:32:40)
at Generator.next (<anonymous>) at /srv/functions/lib/collections/activities/FirebaseActivitiesCollection.js:8:71
at new Promise (<anonymous>) at __awaiter (/srv/functions/lib/collections/activities/FirebaseActivitiesCollection.js:4:12)
at FirebaseActivitiesCollection.getActivitiesByInterval (/srv/functions/lib/collections/activities/FirebaseActivitiesCollection.js:27:16)
I can't track that I have changed anything, could it be that Firebase made some changes that I should be aware of or am I missing an obvious clue in this error message?
My other Cloud Functions and the Firebase JavaScript SDK still work fine.
Extra info: The same code works on my other environment where I have not deployed. This of course led me to search for changes in the deployed code, but I can't find any!?
It seems by the error, that the project was not connected and initialized correctly. As per the official API here, this error occurs when:
Returns the Project ID for this Firestore instance. Validates that
initializeIfNeeded() was called before.
I would recommend you to check that. In case you are still facing, I would say for you to contact the Firebase Free Support. Since you mentioned that it was working until yesterday morning, it might be some change on their side.
Hope this helps!
This turned out to be a very simple matter of initialization of Firebase:
Before I had:
// Initialize firebase
admin.initializeApp(functions.config().firebase)
..And it worked fine until it didn't anymore.
Now I have:
// Initialize firebase
admin.initializeApp()
... And it works again
Got the same error while running some jest tests involving firebase. Problem was that I didn't have GOOGLE_APPLICATION_CREDENTIALS environment variable set.
Since I was running them locally on my machine, exporting this variable in terminal before running the tests was sufficient for my case:
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials/file.json

See continuous logging on command line

I am currently working on a Firebase function. As I am still in the development stage, I have a number of logs in my code to see what's going on.
async function getAddressByIdAsync(address) {
let addr = addressesRef.child(address);
console.log(addr);
return admin.database().ref('Addresses/' + address);
}
The only way I have found to be able to see these logs in real time is though the Firebase console, which is very slow and generally a bad UI experience IMO.
I'm looking for a command line solution that will let me see in real time the logs coming from the Firebase cloud function.
I have tried this command
firebase functions:log
Which appears to return the last twenty or so log entries into my Firebase Functions.
I know Google Cloud has a tail option on the end of that CLI but it doesn't work here.
firebase functions:log tail
Error: Too many arguments. Run firebase help functions:log for usage instructions
Is there a way to get a live running output of the logs from firebase cloud functions?
You can try the local emulator, that way you can first run your functions locally (and log in your terminal), before deploying.
https://firebase.google.com/docs/functions/local-emulator

Retry Cloud Functions for Firebase until it succeeds

I'd like to create a cloud function which sends an e-mail based on a change in my database. I use postmark, but that's not relevant for this function. I looked at the firebase-examples.
My question is: What if the mail service returns an error or if the mail service is temporary down? I don't see any form of error handling in the examples.
My 'solution' would be to try again in 5 minutes for example. Is that possible and advisable in cloud functions?
If you throw an exception when sending the email fails, it should retry the function up to 7 days.
Open detailed usage states for your function in the firebase console
Edit the function
Click the link to configure retry
Enable "Retry on failure"
I haven't tried it myself yet for your use case, but it works for my storage triggered function when it fails.

Resources