{"record":{"id":"3bfe471f579a018b","repo":"LuckyPennySoftware/AutoMapper","slug":"error-building-constructor-projection-strategy","errorCode":null,"errorMessage":"Error building constructor projection strategy.","messagePattern":"Error building constructor projection strategy\\.","errorType":"exception","errorClass":"AutoMapperMappingException","httpStatus":null,"severity":"error","filePath":"src/AutoMapper/QueryableExtensions/ProjectionBuilder.cs","lineNumber":235,"sourceCode":"                            }\n                        }\n                        throw CannotMap(memberMap, resolvedSource.Type);\n                    }\n                }\n            }\n            NewExpression CreateDestination() => typeMap switch\n            {\n                { CustomCtorExpression: LambdaExpression ctorExpression } => (NewExpression)ctorExpression.ReplaceParameters(instanceParameter),\n                { ConstructorMap: { CanResolve: true } constructorMap } =>\n                    New(constructorMap.Ctor, constructorMap.CtorParams.Select(map =>\n                    {\n                        try\n                        {\n                            return TryProjectMember(map, map.DefaultValue(null)) ?? Default(map.DestinationType);\n                        }\n                        catch (Exception e) when (e is not AutoMapperConfigurationException)\n                        {\n                            throw new AutoMapperMappingException(\"Error building constructor projection strategy.\", e, map);\n                        }\n                    })),\n                _ => New(typeMap.DestinationType)\n            };\n        }\n    }\n    static AutoMapperMappingException CannotMap(MemberMap memberMap, Type sourceType) => new(\n        $\"Unable to create a map expression from {memberMap.SourceMember?.DeclaringType?.Name}.{memberMap.SourceMember?.Name} ({sourceType}) to {memberMap.DestinationType.Name}.{memberMap.DestinationName} ({memberMap.DestinationType})\",\n        null, memberMap);\n    [EditorBrowsable(EditorBrowsableState.Never)]\n    sealed class FirstPassLetPropertyMaps(IGlobalConfiguration configuration, MemberPath parentPath, TypePairCount builtProjections) : LetPropertyMaps(configuration, parentPath, builtProjections)\n    {\n        readonly List<SubQueryPath> _savedPaths = [];\n        public override Expression GetSubQueryMarker(LambdaExpression letExpression)\n        {\n            SubQueryPath subQueryPath = new([.. _currentPath.Reverse()], letExpression);\n            var existingPath = _savedPaths.SingleOrDefault(s => s.IsEquivalentTo(subQueryPath));\n            if (existingPath.Marker != null)","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/LuckyPennySoftware/AutoMapper/blob/dfa6dd587c5854b4beee5934beb39ba6e9569b84/src/AutoMapper/QueryableExtensions/ProjectionBuilder.cs#L217-L253","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nCreateProjection<Order, OrderRecord>(); // OrderRecord(int Id, string Label)\nvar q = ctx.Orders.ProjectTo<OrderRecord>(_cfg).ToList(); // throws: 'Label' ctor param unresolvable\n\n// after\nCreateProjection<Order, OrderRecord>()\n    .ForCtorParam(\"Label\", o => o.MapFrom(s => s.Name)); // explicit translatable source\nvar q = ctx.Orders.ProjectTo<OrderRecord>(_cfg).ToList();","handlingStrategy":"try-catch","validationCode":"configuration.AssertConfigurationIsValid();\n// Additionally, for record/positional destinations, unit-test ProjectTo on an\n// in-memory IQueryable so each constructor parameter resolves transitively.","typeGuard":null,"tryCatchPattern":"try\n{\n    result = query.ProjectTo<RecordDest>(_cfg).ToList();\n}\ncatch (AutoMapperMappingException ex) when (ex.Message.Contains(\"constructor projection strategy\"))\n{\n    var root = ex.InnerException;\n    var failingParam = ex.MemberMap?.DestinationName; // ctor param name\n    // add an explicit ForCtorParam(...).MapFrom(translatable) and retry\n}","preventionTips":["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."],"tags":["projection","constructor","entity-framework","queryable","projectto"],"backgroundTag":null,"analyzedSha":"dfa6dd587c5854b4beee5934beb39ba6e9569b84","analyzedAt":"2026-08-13T19:56:33.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}