Firebase Admin refuses to initialize on a Next.js application that has been deployed on Firebase

Currently, I am facing an issue while attempting to deploy a Next JS app to Firebase hosting using the web framework option provided by firebase-tools. The problem arises when trying to initialize firebase-admin as it seems to never properly initialize when fetching data or performing any related tasks. Here is how I am initializing it, which works fine locally:

firebase/firebaseAdminInit.ts

import admin from 'firebase-admin';

export function GetFirebaseAdminApp() {
    if(admin.apps.length === 0){
        const app = admin.initializeApp({
            credential:admin.credential.cert({
                clientEmail: process.env.NEXT_FIREBASE_CLIENT_EMAIL as string,
                projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID as string,
                privateKey: process.env.NEXT_FIREBASE_PRIVATE_KEY as string
            }),
            databaseURL: process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL as string,
            storageBucket: process.env.NEXT_PUBLIC_STORAGE_BUCKET as string
        });
        return app;
    }
    return admin.app();
}

How I use it:

lib/repository/products.ts

import { getFirelord, getFirestore, getDocs, query, orderBy, limit, offset, getCountFromServer, addDoc, updateDoc, getDoc, deleteDoc } from "firelord";
import { ProductsMetaType } from "./dtoModels";
import { Product, ProductRequest, productToDomain, productType_toDto } from "../domain/Products";
import { GetFirebaseAdminApp } from "../../firebase/firebaseAdminInit";
import { PagedQuery, PagedResult } from "../domain/PagedQueries";
import formidable from "formidable";
import { DeleteImage, UploadImage } from "./objectStorage";

const app = getFirestore(GetFirebaseAdminApp()); //This should return the firebase-admin app
const productFl = getFirelord<ProductsMetaType>(app, 'Products');

export async function GetAllProducts() {
    const docs =
        await getDocs(productFl.collection()).then(qSnapshot =>
            qSnapshot.docs.map(docSnapshot => docSnapshot.data())
        ).then(dtoArr => dtoArr.map(productToDomain))
    return docs;
}

Upon logging the app in the firebaseAdminInit.ts file, I can see that there is some value present, not null or undefined. However, when used elsewhere, it fails with an error stating that it's not initialized:

FirebaseAppError: The default Firebase app does not exist. Make sure you call initializeApp() before using any of the Firebase services.

Answer №1

When attempting to incorporate firebase-admin into Next.js API Routes, I encountered a similar issue. Your workaround proved instrumental in identifying the problem. It seems that directly calling admin.app() or getApp() triggers errors in firebase functions. Instead, utilizing getApps()[0] resolves the issue, although the exact reason remains unclear.

The following code enabled me to successfully import adminAuth and adminFirestore from API Routes:

lib/firebase-admin.ts

import { AppOptions, cert, getApps, initializeApp, ServiceAccount } from "firebase-admin/app";
import { getAuth } from "firebase-admin/auth";
import { getFirestore } from "firebase-admin/firestore";

const credentials: ServiceAccount = {
  projectId: process.env.FIREBASE_ADMIN_SDK_FIREBASE_PROJECT_ID,
  privateKey: process.env.FIREBASE_ADMIN_SDK_PRIVATE_KEY?.replace(/\\n/g, "\n"),
  clientEmail: process.env.FIREBASE_ADMIN_SDK_CLIENT_EMAIL,
};

const options: AppOptions = {
  credential: cert(credentials),
};

export const initializeFirebaseAdmin = () => {
  const firebaseAdminApps = getApps();
  if (firebaseAdminApps.length > 0) {
    return firebaseAdminApps[0];
  }

  return initializeApp(options);
}

const firebaseAdmin = initializeFirebaseAdmin();

export const adminAuth = getAuth(firebaseAdmin);
export const adminFirestore = getFirestore(firebaseAdmin);

Answer №2

It seems that attempting to retrieve the app by checking if it has already been initialized or defining a function to determine the environment (development or production) always leads to an error. In order for firebase-admin to run on Firebase functions, it must be initialized in the following manner:

const app = admin.initializeApp({
    credential:admin.credential.cert({
        clientEmail: process.env.NEXT_FIREBASE_CLIENT_EMAIL as string,
        projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID as string,
        privateKey: process.env.NEXT_FIREBASE_PRIVATE_KEY as string
    }),
    databaseURL: process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL as string,
    storageBucket: process.env.NEXT_PUBLIC_STORAGE_BUCKET as string
})

This setup results in errors when testing locally (in development), but functions correctly in production. It can be frustrating to have to repeatedly adjust this code block for deployment or local testing.

I've utilized dependency injection to pass the app to functions requiring firebase-admin, exporting them from the file where initialization occurs. I haven't yet tried simply retrieving the app using admin.app(), which may also work.

Currently, I'm encountering numerous issues with firebase functions related to parsing request bodies and problems with authorization and cookie names. As such, I would advise waiting for better web framework support for Next.js before deploying on Firebase like myself.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

A step-by-step guide on increasing native Time variables in JavaScript

How can I dynamically and repetitively add time (both hours and minutes) in JavaScript to effectively increment a date object? There are times when I need to add minutes, or hours, or a combination of both - and I want the resulting total time to be return ...

I'm facing an issue where Typescript isn't recognizing Jest types

The Challenge Setting up a TypeScript project with Jest has been proving difficult for me. It seems that TypeScript is not recognizing the Jest types from @types/jest, resulting in an error message like this: Cannot find name 'test'. Do you nee ...

Using JavaScript to assign one object to another object

I am facing an issue where I am trying to assign the local variable UgcItems to uploadedItems, but when I attempt to return the value, it shows as undefined. If I place the console.log inside the .getJSON function, then I get the expected value. However, t ...

The v-on:click event handler is not functioning as expected in Vue.js

I am currently learning vue.js and facing some challenges. Below is the code snippet from my HTML page: <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net ...

Executing JavaScript code from an external HTML file

My goal is to create and utilize native web components by defining them as HTML files containing markup, CSS, and Javascript all bundled together in one file, similar to how Vue handles .vue files. These components would be fetched from an external compone ...

Issue Encountered While Attempting to Show a Div Element within a Function

Check out this HTML code snippet: <div class="div1" id ="div1" onclick="onStepClicked()" style ="text-align:center">Step 1</div> And here is the corresponding Script: function onStepClicked() { var elem = document.getElementById(&apo ...

Issue with NextJS version 13.4.2 and NextAuth setup with MongoDB

Looking for a solution to the error message "The top-level-await experiment is not enabled" when integrating MongoDB in the [...nextauth] file of my open-source project, Electronic Patient Records. Check out these helpful links: Project URL: GitHub Repos ...

converting HTML values to TypeScript

I'm a beginner with Angular and could use some assistance. Currently, I have two components - one for the index and another for navigation. Within the index component, there are subcomponents that change based on the value of a variable called produ ...

Having trouble accessing `event.target.value` when selecting an item from the autocomplete feature in Material-UI with the

*** UPDATED CODE BASED ON RECOMMENDATIONS *** I am currently in the process of familiarizing myself with material-ui. I have been exploring how to incorporate event handling with material-ui components, specifically by combining an autocomplete feature wit ...

Is a Javascript-only application compatible with Amazon S3 cloud storage?

I am currently investigating the validity of the following statement: Based on my research, it seems unlikely to create a web application using only JavaScript - without any server-side logic - hosted on Amazon S3 that can also store data solely on S3 whi ...

Despite being present in the node_modules folder, the ag-grid-vue module appears to be missing

Currently, I am diligently following the Vue.js AgGrid getting started tutorial step by step: https://www.ag-grid.com/vuejs-grid/ However, upon adding the <script> section and saving my progress, an error promptly appears: ERROR Failed to compile ...

Issue with parameter functionality not working as expected

This code snippet is not functioning as expected. I am trying to extract and print the values from the URL parameter file:///C:/Users/laddi/Desktop/new%201.html?t=vindu&b=thind function GetURLParameterValue(param) { var pageURL = window. ...

Having trouble with deploying a Next.js monorepo with workspaces on Vercel

Encountering Vercel deployment challenges while transitioning my existing Next.js app to a monorepo using either npm or yarn workspaces. Post the shift to a monorepo, build failures arise due to a package Not found error. View the entire repository on Git ...

The React Material-UI Slider does not move when OnChangeCommitted is triggered

Struggling with implementing the Material UI slider in React, I encountered an issue where the OnChange function would trigger every time the value changed. I needed it to activate only when the left mouse button was released. Fortunately, I discovered a s ...

The $scope object in AngularJS has not been properly defined and

I am facing an issue with retrieving the value of email in my controller. It always returns 'undefined'. Here is my form: <form role="form" novalidate> <div class="form-group"> <input type="email" ng-model="user.emai ...

What is the functionality behind a free hosting website?

Is anyone familiar with websites like Hostinghood, where users can create a subdomain and upload HTML, CSS, etc.? I'm curious about how they operate and how I can create a similar site. This is my first question here, so please respond instead of disl ...

Pinia throws a useStore is not callable error

I have been trying to resolve the issue with (0 , pinia__WEBPACK_IMPORTED_MODULE_1__.useStore) is not a function but unfortunately, I haven't been able to find a solution. Can anyone point out what mistake I am making? Here is my store.js code: im ...

Express encounters difficulties loading JavaScript files

I'm currently working on building an express web app, but I'm encountering a problem with importing a javascript file. Within board.js, there's a line const utility = require('./utility');. However, this line is causing an error: ...

Automate your workflow with Apps Script: Save time by appending a row and seamlessly including additional details to the

I currently have 2 server-side scripts that handle data from an html form. The first script saves user input to the last row available in my Google sheet, while the second script adds additional details to the newly created row. Although both scripts work ...

The preflight styles in twin.macro have their own unique design that sets them apart from those in

After conducting research on the twin.examples repository for Next.js, I discovered that twin.macro suggests integrating their preflight component, which they refer to as <GlobalStyles />. Often, it is aliased as <BaseStyles />, as this compone ...