microsoft/semantic-kernel · error · KernelException
`Always` handlers must not have an eval expression.
Error message
`Always` handlers must not have an eval expression.
What it means
Thrown by DeclarativeEventHandlerGroupBuilder constructor when a condition of type Always has a non-whitespace Expression property. Always conditions are unconditional — they fire on every event regardless of state, so an eval expression is contradictory.
Source
Thrown at dotnet/src/Experimental/Process.Core/ProcessAgentBuilder.cs:307
}
this.DefaultHandler = new DeclarativeEventHandlerBuilder(condition);
}
else if (condition.Type == DeclarativeProcessConditionType.Eval)
{
this.EvalHandlers ??= [];
this.EvalHandlers.Add(new DeclarativeEventHandlerBuilder(condition));
}
else if (condition.Type == DeclarativeProcessConditionType.Always)
{
if (this.DefaultHandler is not null)
{
throw new KernelException("Only one `Always` handler is allowed in a group of event handlers.");
}
if (!string.IsNullOrWhiteSpace(condition.Expression))
{
throw new KernelException("`Always` handlers must not have an eval expression.");
}
this.AlwaysHandler = new DeclarativeEventHandlerBuilder(condition);
}
else
{
throw new KernelException($"Unknown condition type: {condition.Type}");
}
}
}
}
/// <summary>
/// The list of semantic handlers for this group of event handlers.
/// </summary>
public DeclarativeEventHandlerBuilder? AlwaysHandler { get; init; }
/// <summary>View on GitHub (pinned to c028a0c7dc)
Solutions
- Remove the Expression property from any condition with Type == Always.
- If the expression is meaningful, change the condition Type to Eval.
- Validate that Always conditions have null or whitespace Expression before building.
Example fix
// before
var condition = new DeclarativeProcessCondition
{
Type = DeclarativeProcessConditionType.Always,
Expression = "$.retry < 3" // not allowed — throws
};
// after
var condition = new DeclarativeProcessCondition
{
Type = DeclarativeProcessConditionType.Always // no expression
}; Defensive patterns
Strategy: validation
Validate before calling
public static void ValidateAlwaysNoExpression(DeclarativeProcessCondition condition)
{
if (condition.Type == DeclarativeProcessConditionType.Always
&& !string.IsNullOrWhiteSpace(condition.Expression))
{
throw new KernelException("Always conditions must not have an eval expression.");
}
} Prevention
- Never set Expression on Always-type conditions.
- If an expression is needed, use Eval type instead.
- Validate declarative YAML to ensure 'always' handlers have no 'expression' field.
When it happens
Trigger: Creating a DeclarativeProcessCondition with Type == Always and a non-empty Expression string. This can arise from YAML/JSON configuration where an 'always' handler mistakenly includes an expression block.
Common situations: Authoring declarative handler definitions where an 'always' case accidentally carries an expression from a template or copied Eval handler. Deserialization of condition data that populates Expression for all types regardless of condition type.
Related errors
- Only one `Default` handler is allowed in a group of event ha
- `Default` handlers must not have an eval expression.
- Only one `Always` handler is allowed in a group of event han
- Unknown condition type: {condition.Type}
- At least one action must be provided.
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/d673f74c98404e91.
Report an issue: GitHub.