CHR0019: Projection expression lambda must only access members
Rule Description
Section titled “Rule Description”Expression lambdas passed to projection builder methods (e.g. Set(x => ...), To(e => ...), IdentifiedBy(x => ...), UsingKey(e => ...)) must only contain simple member access. They cannot contain method calls, arithmetic, conditional expressions, or any other executable code.
Severity
Section titled “Severity”Error
Example
Section titled “Example”Violation
Section titled “Violation”using Cratis.Chronicle.Projections;
public class UserReadModel { public string Name { get; set; } }public class UserRegistered { public string Name { get; set; } }
public class UserProjection : IProjectionFor<UserReadModel>{ public void Define(IProjectionBuilderFor<UserReadModel> builder) => builder.From<UserRegistered>(evt => evt .Set(x => x.Name) .To(e => e.Name.ToUpper())); // ❌ method call — never executed}using Cratis.Chronicle.Projections;
public class UserReadModel { public string Name { get; set; } }public class UserRegistered { public string Name { get; set; } }
public class UserProjection : IProjectionFor<UserReadModel>{ public void Define(IProjectionBuilderFor<UserReadModel> builder) => builder.From<UserRegistered>(evt => evt .Set(x => x.Name) .To(e => e.Name)); // ✅ simple member access}Why This Rule Exists
Section titled “Why This Rule Exists”In Chronicle’s projection builder, any parameter typed as Expression<Func<...>> is parsed at startup to extract a property path for the read-model mapping—the lambda body is never executed at runtime. Writing method calls, arithmetic (e.Count + 1), conditional expressions (e.Flag ? e.A : e.B), or similar executable code in such a lambda will be silently ignored, producing an incorrect or incomplete projection definition that is very difficult to debug.
The only valid lambda body is a direct property access chain, for example x => x.Property or x => x.Parent.Child.