16

I'm using firebase for auth and db, and AWS lambda for cloud functions.

To add firebase to my JS project, I initializeApp with the firebase config as parameter, as documented here : https://firebase.google.com/docs/web/setup.

As documented here : https://firebase.google.com/docs/admin/setup, I also need to initializeApp in my lambda function.

Something as follows here :

const admin = require('firebase-admin');
const serviceAccount = require('../path/to/service-account.json');

const firebaseAdmin = admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: "dB_URL"
});

The credentials come from the firebase-admin library, so I cannot add this to my web firebase config. So, I need to initialize twice.

However, if I proceed like this, the server will throw an error :

The default Firebase app already exists. This means you called initializeApp() more than once without providing an app name as the second argument. In most cases you only need to call initializeApp() once.But if you do want to initialize multiple apps, pass a second argument to initializeApp() to give each app a unique name.

Am I missing something here ? What's the best practice ? I'm confused.

Someone faced the same issue before it seems : Use Firebase SDK with Netlify Lambda Functions

What worked for this user was to use the REST API as documented here : https://firebase.google.com/docs/projects/api/workflow_set-up-and-manage-project

The documentation says it's in beta though.

Thanks for your kind help

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
John Doe
  • 1,092
  • 3
  • 12
  • 25

3 Answers3

49

It seems that lambda may load the script file that calls admin.initializeApp({...}) multiple times. To prevent the Admin SDK from initializing multiple times, you can for example detect if that already happened:

if (!admin.apps.length) {
    const firebaseAdmin = admin.initializeApp({
        credential: admin.credential.cert(serviceAccount),
        databaseURL: "dB_URL"
    });
}
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Awesome. That worked. Thanks for the tip. Now I have another related issue : I can declare a document reference. However a get() request to get the data containted in that document returns the following error message : "Error getting document: TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type number". It's the error logged from the catch, as in documented here : https://firebase.google.com/docs/firestore/query-data/get-data. Can't tell whether it is Firebase related. Sorry if it's not. – John Doe Sep 04 '19 at 04:02
  • 1
    It looks like you're passing in a number, while keys/ids are always strings. If they're numeric values, convert it to a string first with something like `42.toString()` or `''+42`. Please note that in general it's best to open a new question for... uhm... new questions like this. ;-) – Frank van Puffelen Sep 04 '19 at 04:12
  • I'm sorry, I don't get it. Where am I passing a number ? I'm doing a basic get request, as in the official documentation. Which keys/ids are you referring to ? (Noted. I wasn't sure as it's somewhat related) – John Doe Sep 04 '19 at 04:39
  • If my comment doesn't explain it well enough, open a new question with the [minimal standalone code that anyone can run to reproduce the problem](http://stackoverflow.com/help/mcve). – Frank van Puffelen Sep 04 '19 at 14:15
7

Have similar problem. Based on answer from @Frank van Puffelen ( Thanks to him ), Now a days, Using ES6 ( Firebase admin V >= 9 )

import { initializeApp, applicationDefault, getApps } from "firebase-admin/app";

...

        if ( !getApps().length ) {
            initializeApp({
                credential: applicationDefault(),
                databaseURL: 'https://XXXXXXX.firebaseio.com'
            });
        }
...
Dharman
  • 30,962
  • 25
  • 85
  • 135
Bayu
  • 2,340
  • 1
  • 26
  • 31
3

An alternative in the simplest case might be something like this:

import { initializeApp, getApp } from "firebase-admin/app";

function appSingleton () {
  try {
    return getApp()
  } catch (err) {
    return initializeApp()
  }
}
Brian M. Hunt
  • 81,008
  • 74
  • 230
  • 343