Firebase Admin SDK initialisation error in Firebase studio but works when published

I’m using Firestore in my application to save the generated data and then trying to access it. It works when the application is published, but in the Firebase Studio development environment, for some reason, I’m unable to make it work. The Firebase SDK initialization is just not happening. It’s so stupid. Firebase Studio is running the app inside the Firebase project and it can’t connect to the other resources in the same Firebase project.

Error: Firebase Admin SDK failed to initialize. This is a fatal error for the application. Ensure Firebase project is correctly set up for the current environment. For local development, check Application Default Credentials (ADC) (e.g., gcloud auth application-default login) or GOOGLE_APPLICATION_CREDENTIALS environment variable. The application cannot continue without Firebase. Original error: Cannot read properties of undefined (reading ‘INTERNAL’)
at [project]/src/lib/firebase.ts [app-rsc] (ecmascript) (file:///home/user/studio/.next/server/chunks/ssr/[root-of-the-server]__a6a12f33._.js:1429:15)
at instantiateModule (file:///home/user/studio/.next/server/chunks/ssr/[turbopack]_runtime.js:594:23)
at getOrInstantiateModuleFromParent (file:///home/user/studio/.next/server/chunks/ssr/[turbopack]_runtime.js:653:12)
at esmImport (file:///home/user/studio/.next/server/chunks/ssr/[turbopack]runtime.js:132:20)
at [project]/src/app/actions.ts [app-rsc] (ecmascript) (file:///home/user/studio/.next/server/chunks/ssr/[root-of-the-server]__a6a12f33.
.js:1646:148)
at instantiateModule (file:///home/user/studio/.next/server/chunks/ssr/[turbopack]_runtime.js:594:23)
at getOrInstantiateModuleFromParent (file:///home/user/studio/.next/server/chunks/ssr/[turbopack]_runtime.js:653:12)
at esmImport (file:///home/user/studio/.next/server/chunks/ssr/[turbopack]runtime.js:132:20)
at [project]/.next-internal/server/app/page/actions.js { ACTIONS_MODULE0 => “[project]/src/app/actions.ts [app-rsc] (ecmascript)” } [app-rsc] (server actions loader, ecmascript) (file:///home/user/studio/.next/server/chunks/ssr/[root-of-the-server]__a6a12f33.
.js:2065:147)
at instantiateModule (file:///home/user/studio/.next/server/chunks/ssr/[turbopack]_runtime.js:594:23)
at getOrInstantiateModuleFromParent (file:///home/user/studio/.next/server/chunks/ssr/[turbopack]_runtime.js:653:12)
at esmImport (file:///home/user/studio/.next/server/chunks/ssr/[turbopack]runtime.js:132:20)
at [project]/.next-internal/server/app/page/actions.js { ACTIONS_MODULE0 => “[project]/src/app/actions.ts [app-rsc] (ecmascript)” } [app-rsc] (server actions loader, ecmascript) (file:///home/user/studio/.next/server/chunks/ssr/[root-of-the-server]__a6a12f33.
.js:2089:364)
at instantiateModule (file:///home/user/studio/.next/server/chunks/ssr/[turbopack]_runtime.js:594:23)
at instantiateRuntimeModule (file:///home/user/studio/.next/server/chunks/ssr/[turbopack]_runtime.js:661:12)
at Object.getOrInstantiateRuntimeModule (file:///home/user/studio/.next/server/chunks/ssr/[turbopack]_runtime.js:677:12)
at Object. (file:///home/user/studio/.next/server/app/page.js:29:9)
at Module._compile (node:internal/modules/cjs/loader:1529:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1613:10)
at Module.load (node:internal/modules/cjs/loader:1275:32)
at Module._load (node:internal/modules/cjs/loader:1096:12)
at Module.require (node:internal/modules/cjs/loader:1298:19)
at mod.require (file:///home/user/studio/node_modules/next/dist/server/require-hook.js:65:28)
at require (node:internal/modules/helpers:182:18)
at requirePage (file:///home/user/studio/node_modules/next/dist/server/require.js:103:84)
at loadComponentsImpl (file:///home/user/studio/node_modules/next/dist/server/load-components.js:132:57)
at async DevServer.findPageComponentsImpl (file:///home/user/studio/node_modules/next/dist/server/next-server.js:820:36)
at async DevServer.findPageComponents (file:///home/user/studio/node_modules/next/dist/server/dev/next-dev-server.js:628:16)
at async DevServer.renderPageComponent (file:///home/user/studio/node_modules/next/dist/server/base-server.js:2394:24)
at async DevServer.renderToResponseImpl (file:///home/user/studio/node_modules/next/dist/server/base-server.js:2445:32)
at async DevServer.pipeImpl (file:///home/user/studio/node_modules/next/dist/server/base-server.js:1008:25)
at async NextNodeServer.handleCatchallRenderRequest (file:///home/user/studio/node_modules/next/dist/server/next-server.js:305:17)
at async DevServer.handleRequestImpl (file:///home/user/studio/node_modules/next/dist/server/base-server.js:900:17)
at async (file:///home/user/studio/node_modules/next/dist/server/dev/next-dev-server.js:371:20)
at async Span.traceAsyncFn (file:///home/user/studio/node_modules/next/dist/trace/trace.js:157:20)
at async DevServer.handleRequest (file:///home/user/studio/node_modules/next/dist/server/dev/next-dev-server.js:368:24)
at async invokeRender (file:///home/user/studio/node_modules/next/dist/server/lib/router-server.js:237:21)
at async handleRequest (file:///home/user/studio/node_modules/next/dist/server/lib/router-server.js:428:24)
at async requestHandlerImpl (file:///home/user/studio/node_modules/next/dist/server/lib/router-server.js:452:13)
at async Server.requestListener (file:///home/user/studio/node_modules/next/dist/server/lib/start-server.js:158:13)

1 Like

rt literally, un poco de paciencia dicen, pero tenemos que llegar a la cima

1 Like

The only way I could get this to work in both, is to the AI use CLIENT SDK and rely on firebase rules instead of firebase admin. And it works. But I haven’t figured out the Storage yet. I keep getting the CORS error.

You probably need a .env.local file with the same content as your .env file but ask Gemini if it agrees with my suggestion. Note that Gemini won’t be able to read the .env.local after it’s created as its hidden from Gemini.

The only way I could get it to work with Firestone was to create authenticated user with email/password and use the UID for Firestore rules. Also make sure you don’t have the Studio open in multiple tabs/browsers. It was messing with my authentication. Make sure the .env file has the proper project credentials.

encontre esto: ¡Hola! Excelente y detallada pregunta. Este es un problema clásico de interoperabilidad de módulos (ESM vs. CommonJS) y de configuración de entorno en un entorno de desarrollo gestionado como Firebase Studio. Vamos a desglosar cada punto para solucionarlo.

Aquí tienes una guía completa basada en las mejores prácticas para tu entorno específico (Next.js 15, Turbopack, Firebase Studio).

Resumen de la Solución Principal

El error admin.initializeApp: undefined casi siempre apunta a un problema de importación de módulos, donde no estás obteniendo el objeto SDK principal correctamente. Además, en un entorno gestionado como Firebase Studio, no deberías necesitar gestionar archivos de credenciales JSON manualmente. El entorno ya provee autenticación.

La solución se centra en dos puntos clave:

  1. Corregir la importación del SDK para usar la sintaxis modular moderna (ESM) que Next.js 15 prefiere.
  2. Aprovechar las Credenciales Predeterminadas de la Aplicación (ADC) que Firebase Studio proporciona, eliminando la necesidad de archivos de cuenta de servicio y variables de entorno manuales.

1. Importación e Inicialización de firebase-admin

¿Cuál es el método recomendado para importar e inicializar?

El método recomendado para una aplicación moderna de Next.js es usar la sintaxis de importación de ES Modules (ESM) y aprovechar los puntos de entrada modulares del SDK de Admin. Esto mejora el tree-shaking y la claridad del código.

  • ¿Se debe usar import (ESM) o require (CommonJS)?
    Usa import. Next.js 15 está construido sobre una base de ESM, y Turbopack está optimizado para ello. Mezclar require puede llevar a los problemas que estás viendo.

  • ¿Es esperado el patrón .default?
    Sí, este es un síntoma clásico de interoperabilidad. Cuando intentas usar require() en un módulo que ha sido exportado como ESM, el conjunto de exportaciones del módulo a menudo se agrupa bajo una propiedad default. Tu error Original Init Error: ... (after attempting to resolve via direct require or .default) indica que tu código (o alguna capa intermedia) ya intentó buscar en .default y falló. La solución no es usar .default manualmente, sino usar la sintaxis de importación correcta desde el principio para que el bundler lo resuelva por ti.

Solución de Importación:
No uses import * as admin from 'firebase-admin'; o require('firebase-admin'). En su lugar, importa solo lo que necesitas desde sus puntos de entrada específicos.

// Incorrecto en un entorno ESM moderno
// import * as admin from 'firebase-admin'; // Puede llevar a problemas de resolución
// const admin = require('firebase-admin'); // Evitar en Next.js moderno

// Correcto y recomendado
import { initializeApp, getApps, App } from 'firebase-admin/app';
import { getFirestore } from 'firebase-admin/firestore';

2. Manejo de Credenciales y Variables de Entorno

¿Cómo gestiona Firebase Studio las credenciales?

Firebase Studio es un entorno de desarrollo gestionado y autenticado por Google Cloud.

  • ¿Cómo configurar GOOGLE_APPLICATION_CREDENTIALS?
    No necesitas hacerlo. Deberías eliminar cualquier configuración de esta variable de entorno y borrar el archivo JSON de tu proyecto. Intentar gestionarlo manualmente en un entorno como este es propenso a errores (rutas incorrectas dentro del contenedor, permisos, etc.) y va en contra del diseño del propio entorno.

  • ¿Firebase Studio provee “Application Default Credentials” (ADC)?
    Sí, absolutamente. Al igual que Cloud Functions, Cloud Run y otros servicios de Google Cloud, el entorno de ejecución de Firebase Studio ya está autenticado. Tiene acceso a un token de una cuenta de servicio asociada a tu proyecto de Firebase.

    Esto significa que una llamada a initializeApp() sin argumentos es el método correcto. El SDK detectará automáticamente el entorno y usará las ADC disponibles.

    // Esto es todo lo que necesitas para inicializar en Firebase Studio
    initializeApp();
    

3. Compatibilidad con Turbopack y Dependencias de Servidor

  • ¿Existen problemas de compatibilidad conocidos con Turbopack?
    No hay problemas de compatibilidad fundamentales conocidos entre firebase-admin y Turbopack. El problema que describes es casi con seguridad de resolución de módulos (ESM/CJS), no un bug específico de Turbopack. Al usar la sintaxis de importación de ESM recomendada, tanto Turbopack como el servidor de Node.js de Next.js manejarán la dependencia correctamente.

  • ¿Cómo maneja Firebase Studio las dependencias de servidor?
    Firebase Studio lee tu package.json e instala las dependencias (tanto dependencies como devDependencies) usando npm, yarn o pnpm, de la misma forma que lo harías localmente. El SDK firebase-admin es una dependencia de Node.js estándar y es totalmente compatible. El entorno de ejecución del servidor tiene acceso completo a las dependencias que has instalado en tu proyecto.


4. Diagnóstico y Logs en Firebase Studio

¿Cómo depurar fallos de inicialización?

Dado que no tienes una terminal de npm run dev directa, debes usar las herramientas de logging que proporciona la interfaz de Firebase Studio.

  1. Busca la Pestaña de Logs/Consola: En la interfaz de Firebase Studio, busca un panel o pestaña con un nombre como “Logs”, “Console” o “Terminal”. Este panel mostrará en tiempo real la salida estándar (stdout) y el error estándar (stderr) de tu proceso de servidor Next.js. Aquí es donde aparecerán los errores de inicialización y cualquier console.log que añadas a tu código de backend.

  2. Añade Logs de Diagnóstico: Para depurar, modifica tu archivo de inicialización para registrar el estado de los objetos y variables.

    // En tu archivo src/lib/firebase/admin.ts
    import { initializeApp, getApps } from 'firebase-admin/app';
    
    console.log('Admin module loaded. Checking existing apps...');
    console.log('getApps function type:', typeof getApps);
    console.log('initializeApp function type:', typeof initializeApp);
    
    if (!getApps().length) {
      console.log('No Firebase Admin app initialized yet. Initializing now...');
      try {
        initializeApp();
        console.log('Firebase Admin SDK initialized successfully.');
      } catch (error) {
        console.error('CRITICAL: Error initializing Firebase Admin SDK:', error);
      }
    } else {
      console.log('Firebase Admin app already exists.');
    }
    
    // ... el resto de tu código
    

    Revisa la salida de estos logs en la consola de Firebase Studio para entender exactamente en qué punto está fallando.


5. Ejemplo de Código Mínimo y Funcional

Este es el patrón recomendado para tu archivo src/lib/firebase/admin.ts. Este enfoque asegura que el SDK se inicialice una sola vez (patrón singleton), lo cual es crucial en un entorno de desarrollo con recarga en caliente (hot-reloading) como el de Next.js.

Archivo: src/lib/firebase/admin.ts

import { initializeApp, getApps, App } from 'firebase-admin/app';
import { getFirestore, Firestore } from 'firebase-admin/firestore';
import { getAuth, Auth } from 'firebase-admin/auth';

// Define las variables para las instancias de los servicios de Firebase.
let adminApp: App;
let firestoreAdmin: Firestore;
let authAdmin: Auth;

/**
 * Inicializa el SDK de Firebase Admin si aún no existe una instancia.
 * Este patrón singleton previene inicializaciones múltiples en entornos
 * de desarrollo con hot-reloading.
 *
 * Utiliza las Credenciales Predeterminadas de la Aplicación (ADC)
 * proporcionadas por el entorno de Firebase Studio.
 */
if (!getApps().length) {
  // No hay argumentos en initializeApp() para usar ADC.
  adminApp = initializeApp();
} else {
  // Si ya existe, simplemente obtenemos la instancia por defecto.
  adminApp = getApps()[0];
}

// Obtenemos las instancias de los servicios que necesitamos.
firestoreAdmin = getFirestore(adminApp);
authAdmin = getAuth(adminApp);

// Exportamos las instancias listas para ser usadas en otras partes de la app.
export { adminApp, firestoreAdmin, authAdmin };

Ejemplo de Uso (en una Ruta API o Server Component):

Archivo: src/app/api/test-admin/route.ts

import { NextResponse } from 'next/server';
import { firestoreAdmin } from '@/lib/firebase/admin';

export async function GET() {
  try {
    // Usamos la instancia de Firestore ya inicializada.
    const snapshot = await firestoreAdmin.collection('test').limit(1).get();

    if (snapshot.empty) {
      return NextResponse.json({ message: "No documents found in 'test' collection, but connection is OK." });
    }

    const data = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));

    return NextResponse.json({ success: true, data: data });

  } catch (error: any) {
    console.error('Error accessing Firestore Admin:', error);
    // Devuelve un error 500 con detalles para la depuración.
    return NextResponse.json(
      { success: false, message: 'Failed to connect to Firestore.', error: error.message },
      { status: 500 }
    );
  }
}

Pasos a Seguir:

  1. Elimina tu archivo de credenciales JSON del proyecto.
  2. Elimina cualquier configuración de la variable de entorno GOOGLE_APPLICATION_CREDENTIALS.
  3. Reemplaza el contenido de tu archivo src/lib/firebase/admin.ts con el código funcional proporcionado arriba.
  4. Asegúrate de que tus flujos de Genkit, Rutas API y Server Components importen firestoreAdmin (o los otros servicios) desde '@/lib/firebase/admin'.
  5. Revisa la consola de logs en Firebase Studio para ver los mensajes de inicialización y confirmar que no hay errores.

Siguiendo estos pasos, deberías resolver completamente el problema de inicialización y tener una configuración robusta y correcta para usar firebase-admin en tu proyecto Next.js dentro de Firebase Studio.