LuckyPennySoftware/AutoMapper · error · DuplicateTypeMapConfigurationException

Duplicate CreateMap calls: {error.Types.SourceType.FullName}

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.

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)

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.