When initializing Firebase, you may see:
FirebaseApp with name [DEFAULT] already exists
Flutter may report:
[core/duplicate-app]
A Firebase App named "[DEFAULT]" already exists
The app is attempting to create another FirebaseApp with a name that is already registered.
Initialization versus retrieval
Create a FirebaseApp
Android:
FirebaseApp.initializeApp(context, options)
Flutter:
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
Retrieve an existing FirebaseApp
Android:
FirebaseApp.getInstance()
Flutter:
final app = Firebase.app();
When you only need the existing default app, retrieve it instead of initializing it again.
Android cause 1: Automatic and manual initialization are both enabled
In a standard Android app, FirebaseInitProvider initializes [DEFAULT] automatically.
Manually initializing it again from Application can create a duplicate:
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
FirebaseApp.initializeApp(this, options)
}
}
For a standard setup, remove the manual initialization and retrieve the existing app:
val app = FirebaseApp.getInstance()
Android cause 2: Initialization exists in multiple places
Search the whole project for:
FirebaseApp.initializeApp
FirebaseOptions.Builder
[DEFAULT]
Check locations such as:
- Application
- Activity
- Service
- ContentProvider
- Dependency-injection modules
- Startup managers
- Flavor-specific source sets
Assign responsibility for creating each FirebaseApp to one startup path.
Flutter cause 1: Firebase is initialized outside main as well
Example:
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
await FirebaseService.initialize();
runApp(const MyApp());
}
If FirebaseService.initialize() performs the same Firebase.initializeApp() call, the second call can fail.
Service classes should use existing instances:
class FirebaseService {
FirebaseApp get app => Firebase.app();
FirebaseAuth get auth => FirebaseAuth.instance;
}
Flutter cause 2: Initialization is inside a Widget build method
build() can run many times.
Avoid:
Widget build(BuildContext context) {
Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
return const HomePage();
}
Place initialization in main() or another startup function that runs once.
Flutter cause 3: A Provider is recreated
Initialization inside a Provider or Riverpod factory may run again when its lifecycle recreates the provider.
Initialize during startup and pass the created app into the provider layer:
final app = await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(
ProviderScope(
overrides: [firebaseAppProvider.overrideWithValue(app)],
child: const MyApp(),
),
);
Cause 4: Multiple main files and a shared bootstrap both initialize
A project may contain:
main_development.dart
main_production.dart
bootstrap.dart
Check whether each main file initializes Firebase before calling a shared bootstrap that initializes it again.
A clearer design gives the bootstrap function sole responsibility:
Future<void> bootstrap(FirebaseOptions options) async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: options);
runApp(const MyApp());
}
Cause 5: Two Firebase projects use the same app name
Both calls below use the default name because neither specifies name:
await Firebase.initializeApp(
options: primaryOptions,
);
await Firebase.initializeApp(
options: secondaryOptions,
);
Give the second app a unique name:
final secondary = await Firebase.initializeApp(
name: 'secondary',
options: secondaryOptions,
);
Then obtain services from that named app:
final auth = FirebaseAuth.instanceFor(app: secondary);
A named app is useful only when the application intentionally connects to more than one Firebase project. Do not create extra apps merely to hide a duplicate default initialization.
Cause 6: Old manual Flutter Web initialization remains
Check whether web/index.html still initializes Firebase in JavaScript in addition to Dart:
<script>
firebase.initializeApp(firebaseConfig);
</script>
With a current FlutterFire setup, Firebase initialization should normally be owned by the Dart startup path.
When it happens only after Hot Restart
Hot Restart reruns Dart startup code. A Full Restart may temporarily clear the state, but multiple initialization paths can make the error return.
Check all of the following:
- Search every
initializeAppcall - Review native Android initialization
- Review manual JavaScript initialization on web
- Confirm that different options are not assigned to the same app name
A restart is not a permanent fix for duplicate ownership of initialization.
When it happens in tests
Tests may create the same named app repeatedly.
Use a dedicated name and delete it after the test suite:
late FirebaseApp testApp;
setUpAll(() async {
testApp = await Firebase.initializeApp(
name: 'test-app',
options: testOptions,
);
});
tearDownAll(() async {
await testApp.delete();
});
Avoid using the production [DEFAULT] app as disposable test state.
Inspect registered apps
Android:
FirebaseApp.getApps(context).forEach {
Log.d("Firebase", "${it.name}: ${it.options.projectId}")
}
Flutter:
for (final app in Firebase.apps) {
debugPrint('${app.name}: ${app.options.projectId}');
}
After confirming that an app with the required name exists, replace creation calls with retrieval where appropriate.
Do not catch and ignore the error
Avoid:
try {
await Firebase.initializeApp();
} catch (_) {}
This also hides unrelated configuration and network errors. Identify the duplicate initialization path instead.
Summary
The basic fix for duplicate-app is:
- Search every
initializeAppcall - Do not combine Android automatic and manual default initialization
- Initialize once in Flutter
main()or a single bootstrap function - Do not initialize from rebuildable Widgets or Providers
- Give additional FirebaseApp instances unique names
- Retrieve existing apps with
getInstance()orFirebase.app()
When [DEFAULT] does not exist instead, see Fix Default FirebaseApp Is Not Initialized.
Primary sources
Official references
Check the linked official documentation before a production release.
Continue reading
Related guides
TestCrew
Find testers through mutual testing
Test other Android apps, provide useful feedback, and use earned credits to recruit testers for your own Google Play closed test.
Learn how TestCrew works