PrismLibrary/Prism · error · InvalidOperationException

Mapping with the given type is already registered

Error message

Mapping with the given type is already registered: {0}.

What it means

RegionAdapterMappings.RegisterMapping throws InvalidOperationException (Resources.MappingExistsException) when a mapping for the given control type already exists. The dictionary enforces one adapter per control type to make region adapter resolution deterministic.

Solutions

  1. Only register mappings for control types that do not yet have a mapping (the built-in ones are pre-registered)
  2. Remove duplicate RegisterMapping calls for control types already mapped by Prism defaults
  3. If replacement is truly required, add a non-throwing path: check/replace the mapping via the underlying dictionary or clear it before registering (may require a custom mappings subclass)
  4. Guard the call by checking whether the type is already mapped before registering

Example fix

// before
protected override void ConfigureRegionAdapterMappings(IRegionAdapterMappings mappings)
{
    base.ConfigureRegionAdapterMappings(mappings);
    mappings.RegisterMapping<ScrollView, MyScrollViewAdapter>(); // already registered
}

// after
protected override void ConfigureRegionAdapterMappings(IRegionAdapterMappings mappings)
{
    base.ConfigureRegionAdapterMappings(mappings);
    mappings.RegisterMapping<MyCustomControl, MyCustomControlAdapter>(); // new type only
}
Defensive patterns

Strategy: try-catch

Validate before calling

// RegisterMapping does not expose a TryGetValue; only register custom control types
bool isNewType = myControlType != typeof(ScrollView) && myControlType != typeof(ContentPresenter);

Try / catch

try { mappings.RegisterMapping<MyControl, MyControlAdapter>(); }
catch (InvalidOperationException) { /* mapping already exists — skip or replace via custom mappings */ }

Prevention

When it happens

Trigger: Calling RegisterMapping<TControl, TAdapter> twice for the same TControl — most commonly by overriding ConfigureRegionAdapterMappings in a PrismApp-derived class and re-registering a default adapter that Prism already registered internally, or calling the override both in base and derived bootstrapper code.

Common situations: Customizing region adapters in a Prism.Maui app while the base registration already added the default adapter (e.g. re-registering ContentPresenter/ScrollView adapters); duplicate startup code paths running ConfigureRegionAdapterMappings twice.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


AI-assisted analysis of PrismLibrary/Prism@358118cd64 (2026-09-15). Data as JSON: /api/errors/5308bedad18245f5. Report an issue: GitHub.

Appendix: source

Thrown at src/Maui/Prism.Maui/Navigation/Regions/Adapters/RegionAdapterMappings.cs:25

/// <summary>
/// This class maps <see cref="Type"/> with <see cref="IRegionAdapter"/>.
/// </summary>
public class RegionAdapterMappings
{
    private readonly Dictionary<Type, IRegionAdapter> mappings = [];

    /// <summary>
    /// Registers the mapping between a type and an adapter.
    /// </summary>
    /// <typeparam name="TControl">The type of the control</typeparam>
    /// <typeparam name="TAdapter">The type of the IRegionAdapter to use with the TControl</typeparam>
    /// <exception cref="InvalidOperationException">Throws <see cref="InvalidOperationException"/> when a mapping has already been defined for a specified control type.</exception>
    public void RegisterMapping<TControl, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] TAdapter>() where TAdapter : IRegionAdapter
    {
        var controlType = typeof(TControl);

        if (mappings.ContainsKey(controlType))
            throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
                                                              Resources.MappingExistsException, controlType.Name));

        var adapter = ContainerLocator.Container.Resolve<TAdapter>();

        mappings.Add(controlType, adapter);
    }

    /// <summary>
    /// Removes an existing Registration if one exists and registers the new mapping between a type and an adapter.
    /// </summary>
    /// <typeparam name="TControl">The type of the control</typeparam>
    /// <typeparam name="TAdapter">The type of the IRegionAdapter to use with the TControl</typeparam>
    public void RegisterOrReplaceMapping<TControl, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] TAdapter>() where TAdapter : IRegionAdapter
    {
        var controlType = typeof(TControl);
        var adapter = ContainerLocator.Container.Resolve<TAdapter>();

        if (mappings.ContainsKey(controlType))

View on GitHub (pinned to 358118cd64)