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
- Remove the duplicate CreateMap call from all but one profile so each TypePair is configured exactly once.
- Consolidate the shared map into a single base or common profile and reference that profile from your configuration.
- If you need variations, use Include/IncludeBase to extend a single base map rather than re-declaring CreateMap for the same pair.
- 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
- Maintain a single source of truth for each CreateMap pair — one profile owns it.
- Use a code review checklist item: search for all CreateMap<TSource, TDestination> before adding a new one.
- Run AssertConfigurationIsValid in unit tests and integration test startup to catch duplicates early.
- Consider a Roslyn analyzer or build-time check that flags duplicate CreateMap calls for the same TypePair.
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
- Cannot find any profiles with the name '{profileName}'.
- The type {typeMap.DestinationType.Name} does not have a cons
- {typeMap.DestinationType.Name} does not have a matching cons
- Only member accesses are allowed. {destinationMember}
- Type '{conditionType.Name}' does not implement ICondition<TS
AI-assisted analysis of LuckyPennySoftware/AutoMapper@dfa6dd587c (2026-08-13).
Data as JSON: /api/errors/fc8fb44d16599152.
Report an issue: GitHub.