Firebase Error in Next.js Netlify function

I have a Next.js site https://elijahmanor.com deployed to Netlify and have a function that connects to firebase…

When I look into the logs I get a continual error over and over again

6:18:45 PM: 2020-09-13T23:18:45.942Z a7d45189-7b39-4410-af5d-b3f3a3821ec4 WARN Error enabling offline persistence. Falling back to persistence disabled: Error: ENOENT: no such file or directory, open ‘/src/protos/google/firestore/v1/firestore.proto’

When I hit the function https://elijahmanor.com/.netlify/functions/next_api_getviews?id=test I get the following error
{“errorMessage”:“2020-09-13T23:43:00.614Z c9ffaf84-9361-44eb-a1af-e449e565e121 Task timed out after 10.01 seconds”}

Should I not be using firestore within a function or is there something special that needs to be done for it to work?

Hey @elijahmanor,
A few questions!

  1. Are you using next-on-netlify to build your site? https://github.com/netlify/next-on-netlify
  2. Would you mind sharing your function code here so we can take a look?

I know that people do use firebase-admin in functions. I’m not sure about the offline persistence mentioned in that error though. If Firebase is trying to write to the file system, that will probably not work:

@elijahmanor did you find a solution to this? I am facing the same issue.

I was using X directly, I think I need to switch to using require('firebase-admin') instead of using require('firebase') inside of the function.

I temporarily fixed it by not using functions for firebase and instead I’m making the call directly from my React components (using require("firebase")).

I’m not sure why there are 2 ways to do it. Maybe one is the old way and one is the new way?

I plan to look at this post https://jackwhiting.co.uk/posts/using-firebase-admin-sdk-with-netlify-lambda-functions/ when I get around to trying it again.

Yes, I am using next-on-netlify. I think my problem is that I’m trying to use firebase directly inside the function instead of using firebase-admin. I’m not sure the difference between them. I can get firebase to work from inside my React components, but when I use the same code inside a function I was getting those errors. I’ll try to switch my code soon to use firebase-admin instead. Do you happen to know why one works and the other doesn’t?

I pulled out the code that isn’t working into a gist https://gist.github.com/elijahmanor/ecca498b76f885887e87a5ced0342d26

For now, I took most of that logic and just moved it into a React component and it works, but I’d rather communicate with a API function instead. However, as I mentioned I think moving to use firebase-admin will let me do that. Does that sound right?

Hey there,
Thanks for your patience on this. I… can’t say for sure, to be totally honest! As you probably know from looking around the forum, we’ve seen many folks struggling with firebase-admin in their Netlify Functions. I’ve spent some time tinkering with it and did manage to get a write to a Realtime Database working. Not quite Firestore, but I’ll share what I did in case it’s helpful:

  • copy/pasted the whole Google credentials JSON into an environment variable in the Netlify UI called GOOGLE_APPLICATION_CREDENTIALS
  • manually bundled dependencies with the function in the site’s build command, so something like cd functions/firebase/ && npm install && ../../ && [rest of build command]
// repo structure
src
dist
functions
  |-firebase-func
     |-package.json
     |-firebase.js
// firebase.js
var admin = require("firebase-admin");
var serviceAccount = process.env.GOOGLE_APPLICATION_CREDENTIALS;

// note that an async/await function DOES NOT seem to work with db writes; use an old-school, non-async function
exports.handler = function (event, context) {
    admin.initializeApp({
        credential: admin.credential.cert({
            projectId: JSON.parse(process.env.GOOGLE_APPLICATION_CREDENTIALS).project_id,
            clientEmail: JSON.parse(process.env.GOOGLE_APPLICATION_CREDENTIALS).client_email,
            privateKey: JSON.parse(process.env.GOOGLE_APPLICATION_CREDENTIALS).private_key
            }),
        databaseURL: "https://xxxxxxxxxxx-xxxxxxx.firebaseio.com"
    });
    
    try {
        var db = admin.database()
        var ref = db.ref('flowers')
        var leaves = ref.child("leaves")
        leaves.set({
            1: "round",
            2: "oval",
            3: "symmetrical"
        })
        return { 
            statusCode: 200,
            body: 'Success!'
        }
    } catch (err) {
        return { 
            statusCode: 500, 
            body: err.toString() 
        }
    }
};

Note that even though the write succeeded in the Realtime Database, the function did not return a 200 and ‘Success!’… or a 500. It returned a 502 with a timeout error at the endpoint. Maybe there’s a proper way to clean up the connection after a write? Not sure. I hope this helps! Let us know if you manage to accomplish what you wanted with Firestore.