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

  1. Remove the Expression property from any condition with Type == Always.
  2. If the expression is meaningful, change the condition Type to Eval.
  3. 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

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


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/d673f74c98404e91. Report an issue: GitHub.