microsoft/semantic-kernel · error · ArgumentException
Expression must be a property access expression
Error message
Expression must be a property access expression
What it means
Thrown by ProcessAgentBuilder.ExtractPropertyInfo when the lambda passed to WithUserStateInput is not a chain of property accesses ending at the lambda parameter (e.g., s => s.SomeProperty.NestedProperty). The method walks the expression tree via MemberExpression nodes; if the terminal node is not a ParameterExpression, the expression is rejected as invalid.
Source
Thrown at dotnet/src/Experimental/Process.Core/ProcessAgentBuilder.cs:206
propertyPath.Insert(0, member.Name);
// If this is our first iteration, save the property type
if (propertyType == null)
{
propertyType = ((PropertyInfo)member).PropertyType;
}
// Move to the next level in the expression
expression = memberExpression.Expression;
}
if (expression is ParameterExpression)
{
// We've reached the parameter (e.g., 'myState'), which is good
return (propertyName, propertyPath.ToString(), propertyType ?? typeof(TProperty));
}
throw new ArgumentException("Expression must be a property access expression", nameof(propertySelector));
}
#endregion
internal override KernelProcessStepInfo BuildStep(ProcessBuilder processBuilder, KernelProcessStepStateMetadata? stateMetadata = null)
{
KernelProcessMapStateMetadata? mapMetadata = stateMetadata as KernelProcessMapStateMetadata;
// Build the edges first
var builtEdges = this.Edges.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.Select(e => e.Build()).ToList());
var agentActions = new ProcessAgentActions(
codeActions: new ProcessAgentCodeActions
{
OnComplete = this.OnCompleteCodeAction,
OnError = this.OnCompleteCodeAction
},
declarativeActions: new ProcessAgentDeclarativeActions
{View on GitHub (pinned to c028a0c7dc)
Solutions
- Ensure the lambda is a pure property-access chain from the state parameter, e.g., s => s.MyProperty or s => s.Nested.Property.
- Replace method calls and computed values with direct property accessors on the state type.
- Convert any fields used in the state type to properties (with get/set).
Example fix
// before builder.WithUserStateInput(s => s.CalculateScore()); // method call — throws // after builder.WithUserStateInput(s => s.Score); // direct property access
Defensive patterns
Strategy: validation
Validate before calling
// Validate the expression is a property-access chain before calling WithUserStateInput.
public static bool IsValidPropertyExpression<TState, TProperty>(Expression<Func<TState, TProperty>> expr)
{
var body = expr.Body;
while (body is MemberExpression me)
{
body = me.Expression;
}
return body is ParameterExpression;
} Type guard
public static bool IsPropertyAccessExpression<TState, TProperty>(Expression<Func<TState, TProperty>> expr)
{
var node = expr.Body;
while (node is MemberExpression me)
{
node = me.Expression;
if (me.Member is not PropertyInfo) return false;
}
return node is ParameterExpression;
} Prevention
- Only pass simple property-access lambdas (s => s.Property) to WithUserStateInput.
- Avoid method calls, fields, constants, and closure captures in the expression.
- Ensure state type members are properties, not fields.
When it happens
Trigger: Calling WithUserStateInput with a lambda that accesses a method call, a constant, a field (not a property), or a closure variable instead of a direct property chain on the state object. For example: s => s.ComputeValue() or s => _externalValue would both fail.
Common situations: Passing a computed expression or method invocation to WithUserStateInput instead of a simple property accessor. Using a field instead of a property in the state type. Capturing an external variable in the lambda closure rather than referencing the state parameter directly.
Related errors
- At least one action must be provided.
- All declarative agents must have an Id or a Name assigned.
- AgentDefinition Id must be set
- AgentDefinition.Name cannot be null or empty.
- AgentDefinition.Id cannot be null or empty.
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/7dcd58cb35a883fb.
Report an issue: GitHub.