Description
Operating System
MACOS 15.0.1
Environment (if applicable)
Expo SDK 53 (React Native 0.73 / Hermes enabled by default)
Firebase SDK Version
11.7.1
Firebase SDK Product(s)
Auth
Project Tooling
- Firebase SDK: [email protected]
- React Native: via Expo SDK 53 (React Native 0.73)
- JavaScript Engine: Hermes (default enabled in Expo 53)
- Platform: iOS & Android (Expo Dev Client and EAS Build)
- Bundler: Metro (default from Expo)
- Metro config patch:
- config.resolver.unstable_enablePackageExports = false
- config.resolver.sourceExts.push('cjs')
- Expo CLI: 6.x
- Node.js: 20.x
- Firebase Auth Persistence Attempted:
- initializeAuth() with customAsyncStoragePersistence (fails)
- getAuth() fallback (no crash, but no persistence)
Detailed Problem Description
🧨 Detailed Problem Description
When using initializeAuth()
from the modular Firebase Auth SDK ([email protected]
) in a React Native project via Expo SDK 53 (with Hermes enabled by default), the application crashes at runtime on native platforms (iOS and Android) with the following error:
@firebase/auth: Auth (11.7.1): INTERNAL ASSERTION FAILED: Expected a class definition
Error: INTERNAL ASSERTION FAILED: Expected a class definition, js engine: hermes
This happens even when:
-
initializeAuth()
is wrapped in aPlatform.OS !== "web"
conditional -
initializeAuth()
is lazy-loaded usingimport("firebase/auth")
-
The Metro bundler is patched using:
config.resolver.unstable_enablePackageExports = false; config.resolver.sourceExts.push("cjs");
-
Using a dev client or EAS build (not just Expo Go)
-
Firebase is downgraded to
v10.11.0
(same crash)
In contrast, using getAuth(app)
alone does not crash, but results in non-persistent authentication state on native platforms.
🔍 Additional Notes
- This issue blocks any use of native persistent auth in Firebase Auth when using Expo SDK 53 and Hermes.
- Replacing
initializeAuth()
withgetAuth()
only avoids the crash at the cost of degraded functionality. - The same code worked prior to Expo SDK 53 (e.g. SDK 52 + JSC).
- No issue occurs in Expo Web or when switching the JS engine to JSC in
app.json
, but only in custom clients — Expo Go still uses Hermes.
Steps and code to reproduce issue
Steps to Reproduce
-
Create a new Expo project with SDK 53 and Hermes enabled (default):
npx create-expo-app firebase-crash-test cd firebase-crash-test npx expo install firebase
-
Set up
firebaseConfig.ts
with the following code:// firebaseConfig.ts import { initializeApp, getApps, getApp } from "firebase/app"; import { getAuth } from "firebase/auth"; import { Platform } from "react-native"; const firebaseConfig = { apiKey: "demo", authDomain: "demo.firebaseapp.com", projectId: "demo", storageBucket: "demo.appspot.com", messagingSenderId: "123", appId: "123:web:demo", }; const app = getApps().length ? getApp() : initializeApp(firebaseConfig); let auth = getAuth(app); if (Platform.OS !== "web") { import("firebase/auth") .then(({ initializeAuth }) => { try { initializeAuth(app, { persistence: require("./asyncStoragePersistence").customAsyncStoragePersistence, }); } catch (e: any) { if (e.code !== "auth/already-initialized") throw e; } }) .catch((err) => { console.error("Firebase native auth init error:", err); }); } export { app, auth };
-
Create a dummy
asyncStoragePersistence.ts
file:// asyncStoragePersistence.ts import { getReactNativePersistence } from "firebase/auth/react-native"; import AsyncStorage from "@react-native-async-storage/async-storage"; export const customAsyncStoragePersistence = getReactNativePersistence(AsyncStorage);
-
Use
auth
anywhere in your app (e.g., inApp.tsx
). -
Run the app on Android/iOS using a dev client or EAS build:
npx expo run:android
Result
The app crashes at runtime with this error:
@firebase/auth: Auth (11.7.1): INTERNAL ASSERTION FAILED: Expected a class definition
Error: INTERNAL ASSERTION FAILED: Expected a class definition, js engine: hermes