AvaloniaUI/Avalonia · error · ExpressionParseException

Expected end of expression.

Error message

Expected end of expression.

What it means

BindingExpressionGrammar.Parse throws ExpressionParseException('Expected end of expression.') when the main parse loop exits with State.End but the reader is not exhausted — i.e. a valid expression was parsed and then leftover characters remain that the grammar cannot consume. The grammar requires the entire string to be a single, well-formed expression.

Source

Thrown at src/Avalonia.Base/Data/Core/Parsers/BindingExpressionGrammar.cs:98

                    case State.TypeCast:
                        state = ParseTypeCast(ref r, nodes);
                        break;

                    case State.ElementName:
                        state = ParseElementName(ref r, nodes);
                        mode = SourceMode.Control;
                        break;

                    case State.RelativeSource:
                        state = ParseRelativeSource(ref r, nodes);
                        mode = SourceMode.Control;
                        break;
                }
            }

            if (!r.End)
            {
                throw new ExpressionParseException(r.Position, "Expected end of expression.");
            }

            if (state is State.BeforeMember or State.BeforeMemberNullable)
            {
                throw new ExpressionParseException(r.Position, "Unexpected end of expression.");
            }

            return mode;
        }

        private static State ParseStart(ref CharacterReader r, IList<INode> nodes)
        {
            if (ParseNot(ref r))
            {
                nodes.Add(new NotNode());
                return State.Start;
            }

View on GitHub (pinned to 11c5427268)

Solutions

  1. Ensure the binding path is exactly one valid expression with no trailing characters.
  2. Remove stray separators, duplicate members, or unsupported characters from the path.
  3. If combining logic is needed, use a multi-binding or converter instead of concatenating paths.

Example fix

// before
{Binding Foo bar}
{Binding Foo;Bar}
// after
{Binding Foo}
{Binding Bar}
Defensive patterns

Strategy: try-catch

Validate before calling

// Reject paths with trailing garbage after a valid expression.
static bool PathIsSingleExpression(string path)
{
    try
    {
        var r = new Avalonia.Utilities.CharacterReader(path.AsSpan());
        var (nodes, _) = BindingExpressionGrammar.Parse(ref r);
        return r.End; // true only if the whole string was consumed
    }
    catch { return false; }
}
if (!PathIsSingleExpression(path)) throw new ArgumentException("Malformed binding path.");

Try / catch

try { var (nodes, mode) = BindingExpressionGrammar.Parse(path); }
catch (ExpressionParseException ex) when (ex.Message.Contains("Expected end of expression"))
{ /* remove trailing characters after the valid expression */ }

Prevention

When it happens

Trigger: A binding path with trailing characters after a valid expression, e.g. `Foo bar`, `Foo;bar`, two expressions concatenated, or an operator/character the grammar does not accept at that position.

Common situations: Typos in XAML binding paths; concatenating expressions; stray whitespace-only tokens that break a path; an unsupported character (e.g. `=`) left in the path.

Related errors


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