Type androidx.fragment.app.FragmentKt is defined multiple times — D8, the Android
dex compiler, found the same class in two libraries on the classpath and will not guess which
one you meant.
Adding Xamarin.Firebase.Messaging to a .NET MAUI app pulls in
Xamarin.AndroidX.Fragment.Ktx 1.8.8. MAUI 10 already ships
Xamarin.AndroidX.Fragment 1.9.0, and in 1.9 the AndroidX team moved the Kotlin
extensions — the FragmentKt class — from the -ktx artifact into the
base one. Two archives, one class. Pin Xamarin.AndroidX.Fragment.Ktx to 1.9.0 so
the pair agrees, and the duplicate disappears.
The error
From the first Android build after the Firebase packages were added (abridged — D8 goes on to list the two archives that contain the class):
Type androidx.fragment.app.FragmentKt is defined multiple times
Why it happens
D8 merges every class from every Java archive in the project into the app's dex files. A class that appears twice is not a warning; there is no rule for picking one, so the build stops.
NuGet can't help, because from its point of view nothing is duplicated.
Xamarin.AndroidX.Fragment and Xamarin.AndroidX.Fragment.Ktx are
different packages with different IDs, and each resolved to a perfectly valid version. The
collision is inside the archives they carry: fragment-1.9.0 contains
FragmentKt because 1.9 absorbed the extensions, and fragment-ktx-1.8.8
contains its own copy because 1.8 hadn't yet.
Every MAUI project that adds Firebase meets a version of this. Which AndroidX package clashes changes with each MAUI release, but the shape is constant: the message names the class, the class tells you the package family, and the fix is to make the family agree on one version.
The fix
The Android-only item group in ClinicLive.Pocket.csproj, with its explanation attached:
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
<PackageReference Include="Xamarin.Firebase.Messaging" Version="125.1.1.1" />
<PackageReference Include="Xamarin.GooglePlayServices.Basement" Version="118.10.0.3" />
<!-- Firebase pulls fragment-ktx 1.8.8, MAUI 10 ships fragment 1.9.0, and 1.9 moved
FragmentKt into the base package — D8 then sees it twice ("defined multiple
times"). Pinning ktx to the same 1.9.0 makes them agree. -->
<PackageReference Include="Xamarin.AndroidX.Fragment.Ktx" Version="1.9.0" />
</ItemGroup>
If your duplicate names a different class, find the family first:
dotnet list src/ClinicLive.Pocket package --include-transitive shows which
Xamarin.AndroidX.* versions actually resolved, and the one that disagrees with its
siblings is the one to pin. Pin the older side up to match the newer, not the reverse — MAUI's
own version is the one you can't move.
Where it bit us
Season three, Part 6: push, for
real, the moment the Firebase packages landed and before a single line of push code ran. The
pin is in tag pocket-06 of
the repo. The lesson: the AndroidX
version dance is the toll at the door of every MAUI-plus-Google-library project, and the error
message pays for itself if you read the class name.
Frequently asked
- What does 'Type androidx.fragment.app.FragmentKt is defined multiple times' mean?
- D8, the Android dex compiler, found the FragmentKt class in two Java archives: fragment 1.9.0, which .NET MAUI 10 ships and which now includes the Kotlin extensions, and fragment-ktx 1.8.8, which Xamarin.Firebase.Messaging pulls in and which still carries its own copy. The build stops because a class can only be defined once.
- How do I fix the FragmentKt duplicate in a .NET MAUI app with Firebase?
- Add an explicit PackageReference to Xamarin.AndroidX.Fragment.Ktx at version 1.9.0 in the Android target's item group so it matches the Xamarin.AndroidX.Fragment version MAUI already uses. NuGet then resolves the ktx package to the version that no longer contains the duplicate class.
- Why doesn't NuGet catch the AndroidX version conflict?
- Because Xamarin.AndroidX.Fragment and Xamarin.AndroidX.Fragment.Ktx are separate packages with separate IDs, and each resolved to a valid version. The duplicate is inside the Java archives they carry, which NuGet does not inspect; only D8 sees it when it merges the classes.
More decoded errors in the Fixes category; the season starts at Part 1.