{"record":{"id":"fc8fb44d16599152","repo":"LuckyPennySoftware/AutoMapper","slug":"duplicate-createmap-calls-error-types-sourcetype","errorCode":null,"errorMessage":"Duplicate CreateMap calls:\n{error.Types.SourceType.FullName} to {error.Types.DestinationType.FullName} defined in profiles:\n{ProfileNames}\nThis can cause configuration collisions and inconsistent mappings. Use a single CreateMap call per type pair.","messagePattern":"Duplicate CreateMap calls:\n(.+?) to (.+?) defined in profiles:\n(.+?)\nThis can cause configuration collisions and inconsistent mappings\\. Use a single CreateMap call per type pair\\.","errorType":"validation","errorClass":"DuplicateTypeMapConfigurationException","httpStatus":null,"severity":"error","filePath":"src/AutoMapper/Configuration/ConfigurationValidator.cs","lineNumber":19,"sourceCode":"using AutoMapper.Internal.Mappers;\nnamespace AutoMapper.Configuration;\n\n[EditorBrowsable(EditorBrowsableState.Never)]\npublic class ConfigurationValidator(IGlobalConfiguration config)\n{\n    IGlobalConfigurationExpression Expression => ((MapperConfiguration)config).ConfigurationExpression;\n    public void AssertConfigurationExpressionIsValid(TypeMap[] typeMaps)\n    {\n        var duplicateTypeMapConfigs = Expression.Profiles.Append((Profile)Expression)\n            .SelectMany(p => p.TypeMapConfigs, (profile, typeMap) => (profile, typeMap))\n            .GroupBy(x => x.typeMap.Types)\n            .Where(g => g.Count() > 1)\n            .Select(g => (TypePair: g.Key, ProfileNames: g.Select(tmc => tmc.profile.ProfileName).ToArray()))\n            .Select(g => new DuplicateTypeMapConfigurationException.TypeMapConfigErrors(g.TypePair, g.ProfileNames))\n            .ToArray();\n        if (duplicateTypeMapConfigs.Length != 0)\n        {\n            throw new DuplicateTypeMapConfigurationException(duplicateTypeMapConfigs);\n        }\n        AssertConfigurationIsValid(typeMaps);\n    }\n    public void AssertConfigurationIsValid(TypeMap[] typeMaps)\n    {\n        List<Exception> configExceptions = [];\n        var badTypeMaps =\n            (from typeMap in typeMaps\n             where typeMap.ShouldCheckForValid\n             let unmappedPropertyNames = typeMap.GetUnmappedPropertyNames()\n             let canConstruct = typeMap.PassesCtorValidation\n             where unmappedPropertyNames.Length > 0 || !canConstruct\n             select new AutoMapperConfigurationException.TypeMapConfigErrors(typeMap, unmappedPropertyNames, canConstruct)).ToArray();\n        if (badTypeMaps.Length > 0)\n        {\n            configExceptions.Add(new AutoMapperConfigurationException(badTypeMaps));\n        }\n        HashSet<TypeMap> typeMapsChecked = [];","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/LuckyPennySoftware/AutoMapper/blob/dfa6dd587c5854b4beee5934beb39ba6e9569b84/src/AutoMapper/Configuration/ConfigurationValidator.cs#L1-L37","documentation":"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.","triggerScenarios":"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().","commonSituations":"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.","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."],"exampleFix":"// before — duplicate CreateMap in two profiles\npublic class ProfileA : Profile { public ProfileA() { CreateMap<Source, Dest>(); } }\npublic class ProfileB : Profile { public ProfileB() { CreateMap<Source, Dest>(); } }\n\n// after — single CreateMap in one shared profile\npublic class SharedProfile : Profile { public SharedProfile() { CreateMap<Source, Dest>(); } }","handlingStrategy":"validation","validationCode":"// Before AssertConfigurationIsValid, check for duplicate type pairs across profiles\nvar config = new MapperConfiguration(cfg =>\n{\n    cfg.AddProfile<ProfileA>();\n    cfg.AddProfile<ProfileB>();\n});\nvar allTypePairs = config.ConfigurationExpression.Profiles\n    .Append((Profile)config.ConfigurationExpression)\n    .SelectMany(p => p.TypeMapConfigs, (profile, tmc) => (profile.ProfileName, tmc.Types))\n    .GroupBy(x => x.Types)\n    .Where(g => g.Count() > 1);\nif (allTypePairs.Any())\n    throw new InvalidOperationException(\"Duplicate CreateMap detected: \" +\n        string.Join(\", \", allTypePairs.Select(g => $\"{g.Key.SourceType.Name}->{g.Key.DestinationType.Name}\")));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["configuration","validation","duplicate-mapping","profiles"],"backgroundTag":null,"analyzedSha":"dfa6dd587c5854b4beee5934beb39ba6e9569b84","analyzedAt":"2026-08-13T19:56:33.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}