AvaloniaUI/Avalonia · error · ExpressionParseException

Goto expressions are not supported in binding expressions.

Error message

Goto expressions are not supported in binding expressions.

What it means

BindingExpressionVisitor walks a compiled-binding lambda (expression tree) and only accepts a restricted path subset: property access, indexers, casts, NOT, StreamBinding and delegate creation. VisitGoto rejects GotoExpression, which the C# compiler emits for `return`, `break`, `continue` and `goto` inside expression trees. Control flow is not part of a binding path, so it throws ExpressionParseException during BuildPath.

Source

Thrown at src/Avalonia.Base/Data/Core/Parsers/BindingExpressionVisitor.cs:225

    protected override Expression VisitConditional(ConditionalExpression node)
    {
        throw new ExpressionParseException(0, $"Invalid expression type in binding expression: {node.NodeType}.");
    }

    protected override Expression VisitDynamic(DynamicExpression node)
    {
        throw new ExpressionParseException(0, "Dynamic expressions are not allowed in binding expressions.");
    }

    protected override ElementInit VisitElementInit(ElementInit node)
    {
        throw new ExpressionParseException(0, "Element init expressions are not valid in a binding expression.");
    }

    protected override Expression VisitGoto(GotoExpression node)
    {
        throw new ExpressionParseException(0, "Goto expressions are not supported in binding expressions.");
    }

    protected override Expression VisitInvocation(InvocationExpression node)
    {
        throw new ExpressionParseException(0, $"Invalid expression type in binding expression: {node.NodeType}.");
    }

    protected override Expression VisitLabel(LabelExpression node)
    {
        throw new ExpressionParseException(0, $"Invalid expression type in binding expression: {node.NodeType}.");
    }

    protected override Expression VisitListInit(ListInitExpression node)
    {
        throw new ExpressionParseException(0, $"Invalid expression type in binding expression: {node.NodeType}.");
    }

    protected override Expression VisitLoop(LoopExpression node)

View on GitHub (pinned to 11c5427268)

Solutions

  1. Rewrite the binding lambda as a single expression-bodied member access chain: x => x.Item.Text.
  2. Remove return/break/continue/goto from the compiled-binding lambda.
  3. Keep binding lambdas limited to property/indexer/cast/StreamBinding operations; move any logic into the view-model.

Example fix

// before
CompiledBinding.For(x => { return x.Item.Text; });
// after
CompiledBinding.For(x => x.Item.Text);
Defensive patterns

Strategy: validation

Validate before calling

// Compiled-binding lambdas must be expression-bodied single chains.
// Reject lambdas whose Body is not a supported node type before parsing:
static bool IsValidBindingBody(Expression body) => body switch
{
    MemberExpression or IndexExpression or UnaryExpression
        or MethodCallExpression or ParameterExpression => true,
    _ => false,
};
// Then only pass lambdas that satisfy this to CompiledBinding.For.

Try / catch

try { var path = BindingExpressionVisitor<TIn>.BuildPath<TOut>(expr); }
catch (ExpressionParseException ex)
{
    // log and fall back to a simpler binding expression
}

Prevention

When it happens

Trigger: Writing a block-bodied compiled-binding lambda such as CompiledBinding.For(x => { return x.Item.Text; }), or building an expression tree programmatically that contains a GotoExpression (return/break/continue) and passing it to the compiled-binding path builder.

Common situations: Converting a method body or LINQ query into a binding lambda; using statement-bodied lambdas; libraries that synthesize expression trees with control-flow lowering.

Related errors


AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13). Data as JSON: /api/errors/871758a7dc038b96. Report an issue: GitHub.