-
Notifications
You must be signed in to change notification settings - Fork 954
Description
Operating System
Windows 11 / MAC OS 15
Environment (if applicable)
Expo SDK 53 - Expo SDK 52
Firebase SDK Version
^11.0.0 - 11.10.0
Firebase SDK Product(s)
Auth
Project Tooling
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
When using initializeAuth() from the modular Firebase Auth SDK (firebase@^11.0.0) 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.10.0): INTERNAL ASSERTION FAILED: Expected a class definition
Error: INTERNAL ASSERTION FAILED: Expected a class definition, js engine: hermes
Error: INTERNAL ASSERTION FAILED: Expected a class definition, js engine: hermes
This happens even when:
initializeAuth() is wrapped in a Platform.OS !== "web" conditional
initializeAuth() is lazy-loaded using import("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.
This issue blocks any use of native persistent auth in Firebase Auth when using Expo SDK 53 and Hermes.
Replacing initializeAuth() with getAuth() 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.
**KEY ISSUE -
THE CJS and Enable package exports = false fix.. this seems to fix development but does not fix a native build that would be placed for example on the store.**

When importing firebase auth on a native build.. that has been bundled for the store, there will be an immediate crash. This bug has been here for a long time and even rolling back Firebase versions, Sdk Versions etc.. induces the same bug.
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:
asyncStoragePersistence.ts
Wrap AsyncStorage into the shape getReactNativePersistence expects:
// asyncStoragePersistence.ts
import AsyncStorage from '@react-native-async-storage/async-storage';
import { getReactNativePersistence } from 'firebase/auth/react-native';
export const customAsyncStoragePersistence = getReactNativePersistence(AsyncStorage);
// OR EXPO SECURE STORE
import * as SecureStore from 'expo-secure-store';
import { getReactNativePersistence } from 'firebase/auth/react-native';
const secureStoreWrapper = {
getItem: SecureStore.getItemAsync,
setItem: SecureStore.setItemAsync,
removeItem: SecureStore.deleteItemAsync,
};
export const customAsyncStoragePersistence =
getReactNativePersistence(secureStoreWrapper);
import { initializeApp, getApps, getApp, FirebaseOptions, FirebaseApp } from 'firebase/app';
import {
initializeAuth,
FirebaseAuth,
} from 'firebase/auth/react-native';
import { customAsyncStoragePersistence } from './asyncStoragePersistence';
const firebaseConfig: FirebaseOptions = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_AUTH_DOMAIN",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_STORAGE_BUCKET",
messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
appId: "YOUR_APP_ID",
};
// Initialize or reuse app instance
const app: FirebaseApp = !getApps().length
? initializeApp(firebaseConfig)
: getApp();
// Initialize Auth with React Native persistence
export const auth: FirebaseAuth = initializeAuth(app, {
persistence: customAsyncStoragePersistence,
});
// (Optional) export the raw app if you need other Firebase services
export { app };
Run the app on Android/iOS using a dev client or EAS build:
// App.tsx
import React, { useEffect, useState } from 'react';
import { auth } from './firebaseConfig';
import { onAuthStateChanged, signInAnonymously, User } from 'firebase/auth';
import { Text, View, Button } from 'react-native';
export default function App() {
const [user, setUser] = useState<User | null>(null);
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (u) => {
setUser(u);
});
return unsubscribe;
}, []);
const signIn = () => {
signInAnonymously(auth).catch(console.error);
};
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
{user ? (
Welcome, {user.uid}
) : (
<>
Not signed in
</>
)}
);
}
npx expo run:android
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,