LuckyPennySoftware/AutoMapper · error · InvalidOperationException
Type '{conditionType.Name}' does not implement ICondition<TS
Error message
Type '{conditionType.Name}' does not implement ICondition<TSource, TDestination, TMember> What it means
Thrown by Condition<TCondition>() when the generic type argument does not implement the ICondition<TSource, TDestination, TMember> interface. The CreateConditionExpression method calls GetGenericInterface(typeof(ICondition<,,>)) and throws InvalidOperationException if the result is null, meaning no closed generic ICondition interface was found on the type.
Source
Thrown at src/AutoMapper/Configuration/MemberConfigurationExpression.cs:85
_sourceMembers = ReflectionHelper.GetMemberPath(_sourceType, sourceMembersPath);
PropertyMapActions.Add(pm => pm.MapFrom(sourceMembersPath, _sourceMembers));
}
public void Condition<TCondition>() where TCondition : ICondition<TSource, TDestination, TMember>
{
var expr = CreateConditionExpression(typeof(TCondition));
ConditionCore(expr);
}
protected virtual Expression<Func<TSource, TDestination, TMember, TMember, ResolutionContext, bool>> CreateConditionExpression(Type conditionType)
{
var srcParam = Parameter(typeof(TSource));
var destParam = Parameter(typeof(TDestination));
var srcMemberParam = Parameter(typeof(TMember));
var destMemberParam = Parameter(typeof(TMember));
var ctxParam = Parameter(typeof(ResolutionContext));
var conditionInstance = ServiceLocator(conditionType);
var interfaceType = conditionType.GetGenericInterface(typeof(ICondition<,,>)) ??
throw new InvalidOperationException($"Type '{conditionType.Name}' does not implement ICondition<TSource, TDestination, TMember>");
var evaluateMethod = interfaceType.GetMethod("Evaluate");
// Get the actual types from the interface
var interfaceArgs = interfaceType.GenericTypeArguments;
var expectedSourceType = interfaceArgs[0];
var expectedDestType = interfaceArgs[1];
var expectedMemberType = interfaceArgs[2];
// Cast parameters to the expected types if needed
var srcArg = typeof(TSource) == expectedSourceType ? srcParam : (Expression)Convert(srcParam, expectedSourceType);
var destArg = typeof(TDestination) == expectedDestType ? destParam : (Expression)Convert(destParam, expectedDestType);
var srcMemberArg = typeof(TMember) == expectedMemberType ? srcMemberParam : (Expression)Convert(srcMemberParam, expectedMemberType);
var destMemberArg = typeof(TMember) == expectedMemberType ? destMemberParam : (Expression)Convert(destMemberParam, expectedMemberType);
var callExpression = Call(
Convert(conditionInstance, interfaceType),
evaluateMethod,
srcArg, destArg, srcMemberArg, destMemberArg, ctxParamView on GitHub (pinned to dfa6dd587c)
Solutions
- Implement ICondition<TSource, TDestination, TMember> on your condition class with the exact same generic type arguments as the mapping.
- Alternatively, use one of the lambda Condition(...) overloads instead of a class-based condition.
- Double-check that the condition class's generic arguments match the source, destination, and member types of the ForMember call.
Example fix
// before — wrong interface
public class MyCondition : IValueResolver<Source, Dest, bool> { /* ... */ }
CreateMap<Source, Dest>().ForMember(d => d.IsActive, opt => opt.Condition<MyCondition>());
// after — correct interface with matching generic arguments
public class MyCondition : ICondition<Source, Dest, bool>
{
public bool Evaluate(Source src, Dest dest, bool srcMember, bool destMember, ResolutionContext ctx) => srcMember;
}
CreateMap<Source, Dest>().ForMember(d => d.IsActive, opt => opt.Condition<MyCondition>()); Defensive patterns
Strategy: type-guard
Type guard
// Type guard: verify a type implements ICondition<TSource, TDestination, TMember>
static bool ImplementsCondition<TSource, TDestination, TMember>(Type conditionType)
=> conditionType.GetGenericInterface(typeof(ICondition<,,>)) != null;
// Usage before configuring
if (!ImplementsCondition<Source, Dest, bool>(typeof(MyCondition)))
throw new InvalidOperationException($"{nameof(MyCondition)} must implement ICondition<Source, Dest, bool>."); Prevention
- Always implement ICondition<TSource, TDestination, TMember> with the exact generic arguments matching the map.
- Prefer lambda Condition(...) overloads for simple conditions to avoid interface implementation errors.
- Add a unit test that builds the mapper configuration to catch interface mismatches.
When it happens
Trigger: Calling .Condition<MyCondition>() inside a ForMember callback where MyCondition implements IValueResolver or some other interface instead of ICondition<TSource, TDestination, TMember>. Also happens when MyCondition implements ICondition with different generic type arguments than the map's TSource/TDestination/TMember.
Common situations: Implementing the wrong interface by mistake; using a value resolver class where a condition class was expected; type argument mismatch between the condition's generic arguments and the mapping's types.
Related errors
- Type '{conditionType.Name}' does not implement IPreCondition
- Only interfaces can be proxied. {DestinationType}
- 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/6ebd9e2a18954c35.
Report an issue: GitHub.