LuckyPennySoftware/AutoMapper · error · ArgumentException

The interface has a conflicting property {property.Name}

Error message

The interface has a conflicting property {property.Name}

What it means

Thrown during proxy generation when an interface (or an interface and its inherited interfaces) declares two properties with the same name but incompatible types. The GenerateFields method tracks properties by name in a dictionary; when a name collision occurs and the types are incompatible (the existing property type is not assignable from the new type, or they differ and the new property is writable), it throws ArgumentException.

Source

Thrown at src/AutoMapper/Execution/ProxyGenerator.cs:75

            addIl.Emit(OpCodes.Dup);
            addIl.Emit(OpCodes.Ldfld, propertyChangedField);
            addIl.Emit(OpCodes.Ldarg_1);
            addIl.Emit(OpCodes.Call, delegateMethod);
            addIl.Emit(OpCodes.Castclass, typeof(PropertyChangedEventHandler));
            addIl.Emit(OpCodes.Stfld, propertyChangedField);
            addIl.Emit(OpCodes.Ret);
            typeBuilder.DefineMethodOverride(eventAccessor, method);
        }
        void GenerateFields()
        {
            Dictionary<string, PropertyEmitter> fieldBuilders = [];
            foreach (var property in PropertiesToImplement())
            {
                if (fieldBuilders.TryGetValue(property.Name, out var propertyEmitter))
                {
                    if (propertyEmitter.PropertyType != property.Type && (property.CanWrite || !property.Type.IsAssignableFrom(propertyEmitter.PropertyType)))
                    {
                        throw new ArgumentException($"The interface has a conflicting property {property.Name}", nameof(interfaceType));
                    }
                }
                else
                {
                    fieldBuilders.Add(property.Name, new PropertyEmitter(typeBuilder, property, propertyChangedField));
                }
            }
        }
        List<PropertyDescription> PropertiesToImplement()
        {
            List<PropertyDescription> propertiesToImplement = [];
            List<Type> allInterfaces = [.. interfaceType.GetInterfaces(), interfaceType];
            // first we collect all properties, those with setters before getters in order to enable less specific redundant getters
            foreach (var property in
                allInterfaces.Where(intf => intf != typeof(INotifyPropertyChanged))
                    .SelectMany(intf => intf.GetProperties())
                    .Select(p => new PropertyDescription(p))
                    .Concat(typeDescription.AdditionalProperties))

View on GitHub (pinned to dfa6dd587c)

Solutions

  1. Redesign the interface hierarchy so no two inherited interfaces declare a property with the same name and incompatible types.
  2. Map to a concrete class that disambiguates the conflicting properties instead of using a proxy.
  3. Split the mapping so each conflicting interface is mapped separately.

Example fix

// before — conflicting property names across interfaces
public interface IFoo { string Id { get; set; } }
public interface IBar { int Id { get; set; } }
public interface ICombined : IFoo, IBar { }
CreateMap<Source, ICombined>().AsProxy();

// after — rename one property to avoid conflict
public interface IBar { int Number { get; set; } }
public interface ICombined : IFoo, IBar { }
CreateMap<Source, ICombined>().AsProxy();
Defensive patterns

Strategy: validation

Validate before calling

// Check for conflicting property names across an interface hierarchy before proxying
static bool HasConflictingProperties(Type interfaceType)
{
    var allProps = interfaceType.GetInterfaces().Append(interfaceType)
        .SelectMany(i => i.GetProperties())
        .GroupBy(p => p.Name);
    foreach (var g in allProps)
    {
        var types = g.Select(p => p.PropertyType).Distinct().ToArray();
        if (types.Length > 1 && !types.All(t => types.All(o => t.IsAssignableFrom(o) || o.IsAssignableFrom(t))))
            return true;
    }
    return false;
}

Prevention

When it happens

Trigger: Mapping to an interface that inherits from two other interfaces, each declaring a property with the same name but different types (diamond inheritance conflict). Also triggered when using AsProxy or GetSimilarType on such a conflicting interface.

Common situations: An interface inherits IFoo { string Name } and IBar { int Name }; combining DTO interfaces that accidentally reuse a property name with different types.

Related errors


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