Firebase Admin SDK: firestoreInstance.app is undefined in Firebase Studio/IDX (Node.js v20.19.0, Admin SDK v12.1.1 & v13.4.0)

Hi Firebase Studio / IDX Community & Support,

I’m encountering a persistent issue when trying to use the Firebase Admin SDK (specifically Firestore) within my Firebase Studio (IDX) environment. The core problem is that any Firestore instance obtained via the Admin SDK has its crucial .app property as undefined. This renders the Firestore service unusable.

This issue has been reproduced with multiple Firebase Admin SDK versions and, critically, occurs even in a minimal, standalone Node.js script run directly in the Firebase Studio/IDX terminal, isolating it from my Next.js application’s complexities. The same failure pattern was also observed when deploying my Next.js app (developed in IDX) to Google Cloud Run via the Firebase App Hosting “rollout feature.”

Environment Details:

  • Primary Development Environment: Firebase Studio / Google Cloud Workstations (IDX)
  • Node.js Version in IDX: v20.19.0 (confirmed with node -v)
  • Firebase Admin SDK Versions Tested (in IDX): 12.1.1 (latest stable) and ^13.4.0 (initial version encountered).
  • Original Project Context: Next.js 15.2.3 (App Router).
  • Admin SDK Authentication: Using a service account key (JSON, Base64 encoded in FIREBASE_ADMIN_SDK_CONFIG_BASE64 env var loaded via dotenv in standalone script, and via Next.js env loading in the app).

Problem Description:

When initializing the Firebase Admin SDK:

  1. admin.initializeApp(...) appears to successfully return a FirebaseApp object. Detailed logging shows its constructor.name is FirebaseApp, and it has the correct app name and options.projectId. Its keys include expected service accessors like .firestore().
  2. When a Firestore instance is obtained (either via app.firestore() or the modular getFirestore(app)), the returned object appears to be a Firestore instance (correct constructor.name, typical internal keys).
  3. However, the firestoreInstance.app property is consistently undefined.

This failure prevents validation and use of the Firestore service, leading to adminDb (our module variable for the Firestore client) being null and subsequent operations failing.

Key Finding: The issue is starkly reproduced with both firebase-admin@12.1.1 and firebase-admin@^13.4.0 in the following standalone Node.js script executed directly in the Firebase Studio/IDX terminal:

Standalone Test Script (testAdminSdk.js):

`JavaScript// testAdminSdk.js
require(‘dotenv’).config(); // Loads .env file from project root
const admin = require(‘firebase-admin’);
const { getFirestore: getModularFirestore } = require(‘firebase-admin/firestore’);

const serviceAccountKeyBase64 = process.env.FIREBASE_ADMIN_SDK_CONFIG_BASE64;

if (!serviceAccountKeyBase64) {
console.error(‘TEST-SCRIPT: FIREBASE_ADMIN_SDK_CONFIG_BASE64 is not set in .env file.’);
process.exit(1);
}

let app;
async function runTest() {
try {
const serviceAccountString = Buffer.from(serviceAccountKeyBase64, ‘base64’).toString(‘utf-8’);
const serviceAccount = JSON.parse(serviceAccountString);
const appName = ‘STANDALONE_IDX_TEST_APP_’ + Date.now();

console.log(`TEST-SCRIPT: Initializing Firebase app [${appName}] with projectId "${serviceAccount.project_id}"...`);
app = admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  projectId: serviceAccount.project_id,
  databaseURL: `https://${serviceAccount.project_id}.firebaseio.com` // Included for completeness
}, appName);
console.log(`TEST-SCRIPT: App [${appName}] initialized. Project ID from options: ${app.options.projectId}`);
console.log(`TEST-SCRIPT: App constructor: ${app.constructor?.name}`);

console.log('\nTEST-SCRIPT: Attempt 1: Using app.firestore()');
const db1 = app.firestore();
console.log(`TEST-SCRIPT:   db1 type: ${typeof db1}, constructor: ${db1?.constructor?.name}`);
console.log(`TEST-SCRIPT:   db1.app is defined: ${!!db1?.app}`); // Key check
console.log(`TEST-SCRIPT:   db1.app.name (if defined): ${db1?.app?.name}`);
if (!db1?.app) console.error("TEST-SCRIPT:   ERROR: db1.app is undefined!");

console.log('\nTEST-SCRIPT: Attempt 2: Using getModularFirestore(app)');
const db2 = getModularFirestore(app);
console.log(`TEST-SCRIPT:   db2 type: ${typeof db2}, constructor: ${db2?.constructor?.name}`);
console.log(`TEST-SCRIPT:   db2.app is defined: ${!!db2?.app}`); // Key check
console.log(`TEST-SCRIPT:   db2.app.name (if defined): ${db2?.app?.name}`);
if (!db2?.app) console.error("TEST-SCRIPT:   ERROR: db2.app is undefined!");

} catch (error) {
console.error(‘TEST-SCRIPT: An error occurred:’, error);
} finally {
if (app) {
console.log(\nTEST-SCRIPT: Deleting app [${app.name}]...);
await app.delete();
console.log(‘TEST-SCRIPT: App deleted successfully.’);
}
}
}
runTest();`

Log Output from testAdminSdk.js in Firebase Studio/IDX (with firebase-admin@12.1.1):

`TEST-SCRIPT: Initializing Firebase app [STANDALONE_IDX_TEST_APP_…]…
TEST-SCRIPT: App [STANDALONE_IDX_TEST_APP_…] initialized. Project ID: tripforge-cr566
TEST-SCRIPT: App constructor: FirebaseApp

TEST-SCRIPT: Attempt 1: Using app.firestore()
TEST-SCRIPT: db1 type: object, constructor: Firestore
TEST-SCRIPT: db1.app is defined: false
TEST-SCRIPT: db1.app.name (if defined): undefined
TEST-SCRIPT: ERROR: db1.app is undefined!

TEST-SCRIPT: Attempt 2: Using getModularFirestore(app)
TEST-SCRIPT: db2 type: object, constructor: Firestore
TEST-SCRIPT: db2.app is defined: false
TEST-SCRIPT: db2.app.name (if defined): undefined
TEST-SCRIPT: ERROR: db2.app is undefined!
…`

Summary of My firebaseAdmin.ts for Next.js (where issue was first seen): The module attempts a singleton initialization for a named Firebase Admin app. It loads the service account from the Base64 environment variable, calls admin.initializeApp with the credential, explicit projectId, and databaseURL. It then uses getAuth(app) and attempts app.firestore() (previously getFirestore(app)). Extensive logging in this file confirms the FirebaseApp instance looks valid, but the Firestore instance obtained has firestoreInstance.app === undefined. This failure occurs during next build on Cloud Run (Node.js v20.19.2) and during next dev in IDX.

Questions for the Firebase Studio/IDX Team & Community:

  1. Is this behavior (Firebase Admin SDK’s Firestore service instance having an undefined .app property) a known issue or limitation within the Firebase Studio / IDX Node.js (v20.19.0) environment?
  2. Are there any specific configurations, environment variables, or nuances related to the IDX Node.js runtime that might interfere with the internal mechanisms of the Firebase Admin SDK (versions 12.1.1 or ^13.4.0) responsible for linking service instances to their parent app object?
  3. What could cause a seemingly valid FirebaseApp object to yield Firestore instances (via either app.firestore() or getFirestore(app)) that are not correctly associated with it?
  4. Are there any recommended diagnostic steps, tools, or NODE_DEBUG flags specific to the IDX environment that could help trace this internal SDK linkage failure more effectively?
  5. What is the recommended approach for ensuring stable and correct Firebase Admin SDK (specifically for Firestore) initialization and usage within Firebase Studio/IDX and in apps deployed from IDX to Firebase App Hosting/Cloud Run?

Any insights or guidance you can provide would be greatly appreciated, as this is a fundamental blocker for our server-side Firebase integration. We are happy to provide more detailed logs or run further diagnostic tests as advised.

Thank you for your help!

UPDATE: I have a functioning workaround. I hope others find this useful or have further guidance on how to avoid the workaround in the future.

Recap of Admin SDK Issue: Despite admin.initializeApp() appearing successful and admin.auth().app being correctly linked, admin.firestore().app (and getFirestore(app).app) remained undefined, making the Admin SDK’s Firestore service unusable.

:tada: Breakthrough: Direct @google-cloud/firestore Test SUCCEEDS! :tada:

Following further diagnostics, I tested the standalone @google-cloud/firestore library directly (bypassing the firebase-admin wrapper for Firestore) within the same Firebase Studio/IDX environment, using the same service account credentials. This test was successful! The client initialized correctly, and I was able to perform Firestore operations (listing collections).

Standalone Test Script (testDirectFirestore.js):

`JavaScript// testDirectFirestore.js
require(‘dotenv’).config(); // Loads .env file from project root
const { Firestore } = require(‘@google-cloud/firestore’);

async function runDirectFirestoreTest() {
console.log(‘TEST-DIRECT-FIRESTORE: Starting test…’);
const serviceAccountKeyBase64 = process.env.FIREBASE_ADMIN_SDK_CONFIG_BASE64;

if (!serviceAccountKeyBase64) {
console.error(‘TEST-DIRECT-FIRESTORE: FIREBASE_ADMIN_SDK_CONFIG_BASE64 environment variable is not set.’);
process.exit(1);
}

let serviceAccount;
try {
const serviceAccountString = Buffer.from(serviceAccountKeyBase64, ‘base64’).toString(‘utf-8’);
serviceAccount = JSON.parse(serviceAccountString);
} catch (e) {
console.error(‘TEST-DIRECT-FIRESTORE: Failed to decode or parse the service account JSON.’, e);
process.exit(1);
}

if (!serviceAccount.project_id || !serviceAccount.client_email || !serviceAccount.private_key) {
console.error(‘TEST-DIRECT-FIRESTORE: Service account JSON is missing required fields.’);
process.exit(1);
}

console.log(TEST-DIRECT-FIRESTORE: Attempting to initialize @google-cloud/firestore client...);
console.log(TEST-DIRECT-FIRESTORE: Using projectId: ${serviceAccount.project_id});

let firestoreClient;
try {
firestoreClient = new Firestore({
projectId: serviceAccount.project_id,
credentials: {
client_email: serviceAccount.client_email,
private_key: serviceAccount.private_key.replace(/\n/g, ‘\n’),
},
});
console.log(‘TEST-DIRECT-FIRESTORE: @google-cloud/firestore client initialized successfully.’);

console.log('\nTEST-DIRECT-FIRESTORE: Attempting to list collections...');
const collections = await firestoreClient.listCollections();
console.log('TEST-DIRECT-FIRESTORE: Successfully listed collections. Count:', collections.length);
collections.forEach(collection => {
  console.log(`  - Found collection with id: ${collection.id}`);
});
console.log('\nTEST-DIRECT-FIRESTORE: SUCCESS - Direct @google-cloud/firestore test completed without errors.');

} catch (error) {
console.error(‘\nTEST-DIRECT-FIRESTORE: An error occurred during the test:’, error);
console.log(‘\nTEST-DIRECT-FIRESTORE: FAILED - Direct @google-cloud/firestore test encountered an error.’);
}
}
runDirectFirestoreTest();`

Successful Output from testDirectFirestore.js in IDX:

`TEST-DIRECT-FIRESTORE: Starting test…
TEST-DIRECT-FIRESTORE: Attempting to initialize @google-cloud/firestore client…
TEST-DIRECT-FIRESTORE: Using projectId: tripforge-cr566
TEST-DIRECT-FIRESTORE: @google-cloud/firestore client initialized successfully.

TEST-DIRECT-FIRESTORE: Attempting to list collections (requires Datastore Owner/User role on service account)…
TEST-DIRECT-FIRESTORE: Successfully listed collections. Count: 3

  • Found collection with id: airports
  • Found collection with id: countrySummaries
  • Found collection with id: itineraries

TEST-DIRECT-FIRESTORE: SUCCESS - Direct @google-cloud/firestore test completed without errors.`

Proposed Workaround for Next.js Application: Given this success, I plan to modify my Next.js application to:

  1. Continue using firebase-admin (e.g., adminAuth = getAuth(adminApp)) for Firebase Authentication features (like ID token verification in API routes), as adminAuth.app was correctly linked in our tests.
  2. Create a new module (e.g., src/lib/directFirestoreClient.ts) that initializes and exports a singleton Firestore client using @google-cloud/firestore directly, similar to the testDirectFirestore.js script.
  3. Update my Next.js API routes (e.g., src/app/api/v1/profile/route.ts) to import and use this directDb client for all Firestore operations, instead of the problematic adminDb from firebase-admin.

Questions for the Firebase Studio/IDX Community on this Workaround:

  1. Is this a sound and recommended strategy for server-side Firestore access in a Next.js application within the Firebase Studio/IDX environment, given the issues with firebase-admin’s Firestore module?
  2. What are the best practices for managing the lifecycle and instantiation of the @google-cloud/firestore client in a serverless Next.js API route context (e.g., should directFirestoreClient.ts implement a singleton pattern to reuse the client instance across requests)?
  3. Are there any known caveats, performance implications, or things to watch out for when using @google-cloud/firestore directly alongside firebase-admin (which would only be used for Auth) in the same application?
  4. When using @google-cloud/firestore directly in API routes:
  • How should types like Timestamp be handled? (e.g., import from @google-cloud/firestore?)
  • How should server timestamps be written? (e.g., using FieldValue.serverTimestamp() from @google-cloud/firestore?)
  1. Does this approach introduce any significant differences in how Firestore Security Rules are evaluated compared to if firebase-admin was used (assuming firebase-admin bypasses rules, the direct client would still effectively have admin rights via the service account, but client SDKs used by users would be subject to rules)? Self-correction: The standalone @google-cloud/firestore client, when initialized with service account credentials, also bypasses security rules by default, similar to firebase-admin.

I appreciate any advice, best practices, or potential pitfalls related to this workaround strategy for using Firestore server-side in Firebase Studio/IDX. While this workaround seems promising for Firestore, the underlying issue with firebase-admin’s Firestore module remains a concern.

Thank you!