LuckyPennySoftware/AutoMapper · error · AutoMapperMappingException
Error building constructor projection strategy.
Error message
Error building constructor projection strategy.
What it means
During ProjectTo, ProjectionBuilder.CreateDestination builds the destination via a constructor call, projecting each constructor parameter with TryProjectMember. Any exception other than AutoMapperConfigurationException thrown while resolving a parameter is wrapped in AutoMapperMappingException carrying the failing ConstructorParameterMap and the original as InnerException.
Source
Thrown at src/AutoMapper/QueryableExtensions/ProjectionBuilder.cs:235
}
}
throw CannotMap(memberMap, resolvedSource.Type);
}
}
}
NewExpression CreateDestination() => typeMap switch
{
{ CustomCtorExpression: LambdaExpression ctorExpression } => (NewExpression)ctorExpression.ReplaceParameters(instanceParameter),
{ ConstructorMap: { CanResolve: true } constructorMap } =>
New(constructorMap.Ctor, constructorMap.CtorParams.Select(map =>
{
try
{
return TryProjectMember(map, map.DefaultValue(null)) ?? Default(map.DestinationType);
}
catch (Exception e) when (e is not AutoMapperConfigurationException)
{
throw new AutoMapperMappingException("Error building constructor projection strategy.", e, map);
}
})),
_ => New(typeMap.DestinationType)
};
}
}
static AutoMapperMappingException CannotMap(MemberMap memberMap, Type sourceType) => new(
$"Unable to create a map expression from {memberMap.SourceMember?.DeclaringType?.Name}.{memberMap.SourceMember?.Name} ({sourceType}) to {memberMap.DestinationType.Name}.{memberMap.DestinationName} ({memberMap.DestinationType})",
null, memberMap);
[EditorBrowsable(EditorBrowsableState.Never)]
sealed class FirstPassLetPropertyMaps(IGlobalConfiguration configuration, MemberPath parentPath, TypePairCount builtProjections) : LetPropertyMaps(configuration, parentPath, builtProjections)
{
readonly List<SubQueryPath> _savedPaths = [];
public override Expression GetSubQueryMarker(LambdaExpression letExpression)
{
SubQueryPath subQueryPath = new([.. _currentPath.Reverse()], letExpression);
var existingPath = _savedPaths.SingleOrDefault(s => s.IsEquivalentTo(subQueryPath));
if (existingPath.Marker != null)View on GitHub (pinned to dfa6dd587c)
Solutions
- Inspect ex.InnerException and the failing constructor parameter (the map in the exception) to identify which ctor arg broke.
- Provide an explicit ForCtorParam("name").MapFrom(...) with an EF-translatable expression, or MapFrom a concrete source member.
- Give the parameter a translatable default via ForCtorParam(...).MapFrom, or use a parameterless-constructable destination type.
- Ensure nested types referenced by ctor params have their own CreateProjection/CreateMap.
Example fix
// before
CreateProjection<Order, OrderRecord>(); // OrderRecord(int Id, string Label)
var q = ctx.Orders.ProjectTo<OrderRecord>(_cfg).ToList(); // throws: 'Label' ctor param unresolvable
// after
CreateProjection<Order, OrderRecord>()
.ForCtorParam("Label", o => o.MapFrom(s => s.Name)); // explicit translatable source
var q = ctx.Orders.ProjectTo<OrderRecord>(_cfg).ToList(); Defensive patterns
Strategy: try-catch
Validate before calling
configuration.AssertConfigurationIsValid(); // Additionally, for record/positional destinations, unit-test ProjectTo on an // in-memory IQueryable so each constructor parameter resolves transitively.
Try / catch
try
{
result = query.ProjectTo<RecordDest>(_cfg).ToList();
}
catch (AutoMapperMappingException ex) when (ex.Message.Contains("constructor projection strategy"))
{
var root = ex.InnerException;
var failingParam = ex.MemberMap?.DestinationName; // ctor param name
// add an explicit ForCtorParam(...).MapFrom(translatable) and retry
} Prevention
- For every constructor parameter that has no natural source member, add an explicit ForCtorParam MapFrom.
- Keep ctor-param MapFrom expressions translatable by the EF provider.
- Ensure child types used as ctor parameters have their own CreateProjection.
When it happens
Trigger: ProjectTo onto a type with a parameterized constructor (record, immutable DTO) where a constructor parameter cannot be resolved or translated: ForCtorParam with an untranslatable MapFrom, a ctor param with no matching source member and no usable default, or a nested projection missing its map.
Common situations: Records/positional DTOs with required ctor params; ForCtorParam MapFrom calling unsupported methods; ctor parameter name not matching any source member after a rename; migrating from class-with-setters to records.
Related errors
- Error building queryable mapping strategy.
- CreateProjection works with ProjectTo, not with Map.
- The type {typeMap.DestinationType.Name} does not have a cons
- {typeMap.DestinationType.Name} does not have a matching cons
- Error building constructor parameter mapping strategy.
AI-assisted analysis of LuckyPennySoftware/AutoMapper@dfa6dd587c (2026-08-13).
Data as JSON: /api/errors/3bfe471f579a018b.
Report an issue: GitHub.