LuckyPennySoftware/AutoMapper · error · InvalidOperationException
Only interfaces can be proxied. {DestinationType}
Error message
Only interfaces can be proxied. {DestinationType} What it means
Thrown by AsProxy() when the destination type is not an interface. AutoMapper's proxy generation uses System.Reflection.Emit to build a dynamic concrete class implementing the interface, including INotifyPropertyChanged support. It can only proxy interface types because it generates a class that implements them.
Source
Thrown at src/AutoMapper/Configuration/TypeMapConfiguration.cs:383
IgnoreDestinationMember(property);
}
return this as TMappingExpression;
}
public TMappingExpression IgnoreAllSourcePropertiesWithAnInaccessibleSetter()
{
foreach (var property in PropertiesWithAnInaccessibleSetter(SourceType))
{
ForSourceMemberCore(property, options => options.DoNotValidate());
}
return this as TMappingExpression;
}
private static IEnumerable<PropertyInfo> PropertiesWithAnInaccessibleSetter(Type type) => type.GetRuntimeProperties().Where(p => p.GetSetMethod() == null);
public void ConvertUsing(Expression<Func<TSource, TDestination>> mappingFunction) => SetTypeConverter(new ExpressionTypeConverter(mappingFunction));
public TMappingExpression AsProxy()
{
if (!DestinationType.IsInterface)
{
throw new InvalidOperationException("Only interfaces can be proxied. " + DestinationType);
}
TypeMapActions.Add(tm => tm.AsProxy());
return this as TMappingExpression;
}
}View on GitHub (pinned to dfa6dd587c)
Solutions
- Define an interface for the destination contract and map to that interface, then call AsProxy().
- If you need a concrete destination, map to a concrete class with a public constructor instead of using AsProxy.
Example fix
// before — destination is a class
public class Dest { public string Name { get; set; } }
CreateMap<Source, Dest>().AsProxy();
// after — destination is an interface
public interface IDest { string Name { get; set; } }
CreateMap<Source, IDest>().AsProxy(); Defensive patterns
Strategy: validation
Validate before calling
// Check destination is an interface before calling AsProxy
if (!typeof(TDestination).IsInterface)
throw new InvalidOperationException($"{typeof(TDestination).Name} is not an interface. AsProxy only works with interfaces."); Type guard
// Compile-time guard via generic constraint
// Only allow interface destinations for AsProxy usage
static void ConfigureProxyMap<TSource, TDestination>()
where TDestination : class // ideally also an interface
{
if (!typeof(TDestination).IsInterface)
throw new InvalidOperationException("AsProxy requires an interface destination type.");
} Prevention
- Only call AsProxy when the destination type is an interface.
- Define interfaces for your DTO contracts and map to those when you need proxy behavior.
- Use a runtime IsInterface check in shared helper code to fail fast with a clear message.
When it happens
Trigger: Calling .AsProxy() on a CreateMap<TSource, TDestination>() where TDestination is a concrete class, struct, or abstract class rather than an interface.
Common situations: Trying to proxy a concrete class to auto-fill read-only or init-only properties; misunderstanding that AsProxy generates an implementation for an interface contract.
Related errors
- Type '{conditionType.Name}' does not implement ICondition<TS
- Type '{conditionType.Name}' does not implement IPreCondition
- The type {typeMap.DestinationType.Name} does not have a cons
- Only member accesses are allowed. {destinationMember}
- sourceExpression may not be null when mapping {DestinationMe
AI-assisted analysis of LuckyPennySoftware/AutoMapper@dfa6dd587c (2026-08-13).
Data as JSON: /api/errors/284138216e5f75c4.
Report an issue: GitHub.