{"record":{"id":"a2c6992cadfac57b","repo":"devlooped/moq","slug":"expression-is-not-a-property-access-0","errorCode":null,"errorMessage":"Expression is not a property access: {0}","messagePattern":"Expression is not a property access: (.+?)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Moq/ExpressionExtensions.cs","lineNumber":405,"sourceCode":"                        (derivedProperty.CanWrite(out var setter) && setter.GetBaseDefinition() == property.GetSetMethod(true)))\n                        return derivedProperty;\n                }\n            }\n\n            return property;\n        }\n\n        /// <summary>\n        /// Converts the body of the lambda expression into the <see cref=\"PropertyInfo\"/> referenced by it.\n        /// </summary>\n        public static PropertyInfo ToPropertyInfo(this LambdaExpression expression)\n        {\n            if (expression.Body is MemberExpression prop)\n            {\n                return prop.GetReboundProperty();\n            }\n\n            throw new ArgumentException(string.Format(\n                CultureInfo.CurrentCulture,\n                Resources.SetupNotProperty,\n                expression.ToStringFixed()));\n        }\n\n        /// <summary>\n        /// Checks whether the body of the lambda expression is a property access.\n        /// </summary>\n        public static bool IsProperty(this LambdaExpression expression)\n        {\n            Debug.Assert(expression != null);\n\n            return expression.Body is MemberExpression memberExpression && memberExpression.Member is PropertyInfo;\n        }\n\n        /// <summary>\n        ///   Checks whether the body of the lambda expression is a indexer access.\n        /// </summary>","sourceCodeStart":387,"sourceCodeEnd":423,"githubUrl":"https://github.com/devlooped/moq/blob/89a5be629c752960fe403e95ff583e4ae6f00542/src/Moq/ExpressionExtensions.cs#L387-L423","documentation":"ToPropertyInfo extracts property metadata from an expression used in a property setup. It requires the lambda body to be a MemberExpression referring to a property access; anything else throws ArgumentException 'Expression is not a property access: {0}'. This keeps property setup APIs (mock.SetupProperty / Stub-style APIs) restricted to real properties.","triggerScenarios":"Passing a non-property lambda to an API that calls ToPropertyInfo: `x => x.Method()`, `x => x.Field + 1`, `x => x.Prop.Value` when Prop.Value resolves oddly, or an indexer access `x => x[0]`.","commonSituations":"Setting up fields instead of properties; accidentally passing method getters; writing `x => x.SomeProperty.SubProperty` where the target API expects a single-level property on the mock's type; dynamic/expanded expressions whose body is not MemberExpression.","solutions":["Pass a direct property access on the lambda parameter: `x => x.PropertyName`.","If you intended method setup, use `mock.Setup(x => x.Method())` instead of the property API.","Ensure the member is a public instance property, not a field — convert the field to a property if needed.","Verify the lambda body compiles to MemberExpression with NodeType MemberAccess; simplify multi-level chains to the property directly owned by the mock type."],"exampleFix":"// before\nmock.SetupProperty(x => x.Compute()); // method, not property\n// after\nmock.SetupProperty(x => x.Value);","handlingStrategy":"type-guard","validationCode":"static bool IsPropertyAccess<T, R>(Expression<Func<T, R>> e) =>\n    e.Body is MemberExpression { Member: PropertyInfo };","typeGuard":"static bool IsDirectProperty<T, R>(Expression<Func<T, R>> e) =>\n    e.Body is MemberExpression { Member: PropertyInfo p, Expression: ParameterExpression }\n    && p.CanRead;","tryCatchPattern":"try\n{\n    mock.SetupProperty(expr);\n}\ncatch (ArgumentException ex) when (ex.Message.StartsWith(\"Expression is not a property access\"))\n{\n    // switch to mock.Setup(...) for methods or fix the lambda\n}","preventionTips":["Only pass single-level property lambdas like x => x.Prop to property APIs","Fields are not properties — convert fields to properties before setup","Use Setup(...) for method calls and computed expressions","Validate the member type with reflection in helper wrappers"],"tags":["moq","linq-expressions","argument-exception","property-setup"],"backgroundTag":"invalid-argument","analyzedSha":"89a5be629c752960fe403e95ff583e4ae6f00542","analyzedAt":"2026-09-16T05:31:39.496Z","contentChangedAt":"2026-09-16T05:31:39.496Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}