LuckyPennySoftware/AutoMapper · error · DuplicateTypeMapConfigurationException

Duplicate CreateMap calls

Error message

Duplicate CreateMap calls:
{error.Types.SourceType.FullName} to {error.Types.DestinationType.FullName} defined in profiles:
{ProfileNames}
This can cause configuration collisions and inconsistent mappings. Use a single CreateMap call per type pair.

What it means

Thrown during AssertConfigurationIsValid when two or more profiles (or the global configuration plus a profile) each contain a CreateMap for the exact same source-to-destination TypePair. AutoMapper requires a single canonical configuration per type pair because duplicates produce unpredictable collisions: only one TypeMap wins and the others' member rules are silently lost. The validator groups all TypeMapConfigs by their Types key and fails when any group has a count greater than one.

Solutions

  1. Remove the duplicate CreateMap call from all but one profile so each TypePair is configured exactly once.
  2. Consolidate the shared map into a single base or common profile and reference that profile from your configuration.
  3. If you need variations, use Include/IncludeBase to extend a single base map rather than re-declaring CreateMap for the same pair.
  4. Search the codebase for all CreateMap<TSource, TDestination> occurrences and keep only one.

Example fix

// before — duplicate CreateMap in two profiles
public class ProfileA : Profile { public ProfileA() { CreateMap<Source, Dest>(); } }
public class ProfileB : Profile { public ProfileB() { CreateMap<Source, Dest>(); } }

// after — single CreateMap in one shared profile
public class SharedProfile : Profile { public SharedProfile() { CreateMap<Source, Dest>(); } }
Defensive patterns

Strategy: validation

Validate before calling

// Before AssertConfigurationIsValid, check for duplicate type pairs across profiles
var config = new MapperConfiguration(cfg =>
{
    cfg.AddProfile<ProfileA>();
    cfg.AddProfile<ProfileB>();
});
var allTypePairs = config.ConfigurationExpression.Profiles
    .Append((Profile)config.ConfigurationExpression)
    .SelectMany(p => p.TypeMapConfigs, (profile, tmc) => (profile.ProfileName, tmc.Types))
    .GroupBy(x => x.Types)
    .Where(g => g.Count() > 1);
if (allTypePairs.Any())
    throw new InvalidOperationException("Duplicate CreateMap detected: " +
        string.Join(", ", allTypePairs.Select(g => $"{g.Key.SourceType.Name}->{g.Key.DestinationType.Name}")));

Prevention

When it happens

Trigger: Registering two Profile classes that both call CreateMap<Source, Dest>(), or calling CreateMap<TSource, TDestination>() at the global config level and also inside a Profile for the same pair, then invoking mapper.ConfigurationProvider.AssertConfigurationIsValid().

Common situations: A shared mapping is accidentally duplicated across profiles during refactoring; copy-paste of CreateMap between profile files; multiple team members adding the same map in different files; merging feature branches that each added the same mapping.

Related errors


AI-assisted analysis of LuckyPennySoftware/AutoMapper@dfa6dd587c (2026-08-13). Data as JSON: /api/errors/fc8fb44d16599152. Report an issue: GitHub.

Appendix: source

Thrown at src/AutoMapper/Configuration/ConfigurationValidator.cs:19

using AutoMapper.Internal.Mappers;
namespace AutoMapper.Configuration;

[EditorBrowsable(EditorBrowsableState.Never)]
public class ConfigurationValidator(IGlobalConfiguration config)
{
    IGlobalConfigurationExpression Expression => ((MapperConfiguration)config).ConfigurationExpression;
    public void AssertConfigurationExpressionIsValid(TypeMap[] typeMaps)
    {
        var duplicateTypeMapConfigs = Expression.Profiles.Append((Profile)Expression)
            .SelectMany(p => p.TypeMapConfigs, (profile, typeMap) => (profile, typeMap))
            .GroupBy(x => x.typeMap.Types)
            .Where(g => g.Count() > 1)
            .Select(g => (TypePair: g.Key, ProfileNames: g.Select(tmc => tmc.profile.ProfileName).ToArray()))
            .Select(g => new DuplicateTypeMapConfigurationException.TypeMapConfigErrors(g.TypePair, g.ProfileNames))
            .ToArray();
        if (duplicateTypeMapConfigs.Length != 0)
        {
            throw new DuplicateTypeMapConfigurationException(duplicateTypeMapConfigs);
        }
        AssertConfigurationIsValid(typeMaps);
    }
    public void AssertConfigurationIsValid(TypeMap[] typeMaps)
    {
        List<Exception> configExceptions = [];
        var badTypeMaps =
            (from typeMap in typeMaps
             where typeMap.ShouldCheckForValid
             let unmappedPropertyNames = typeMap.GetUnmappedPropertyNames()
             let canConstruct = typeMap.PassesCtorValidation
             where unmappedPropertyNames.Length > 0 || !canConstruct
             select new AutoMapperConfigurationException.TypeMapConfigErrors(typeMap, unmappedPropertyNames, canConstruct)).ToArray();
        if (badTypeMaps.Length > 0)
        {
            configExceptions.Add(new AutoMapperConfigurationException(badTypeMaps));
        }
        HashSet<TypeMap> typeMapsChecked = [];

View on GitHub (pinned to dfa6dd587c)