AvaloniaUI/Avalonia · error · ExpressionParseException

Unexpected end of expression.

Error message

Unexpected end of expression.

What it means

Thrown by BindingExpressionGrammar.Parse at the end of the main parse loop when the parser is in the BeforeMember or BeforeMemberNullable state. This state means the last token consumed was a member-access operator ('.' or '?.') but no member identifier followed it before the string ended. Avalonia's binding path grammar requires every accessor to be followed by a concrete member name, so a dangling dot is a syntax error.

Source

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

                        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;
            }

            else if (ParseSharp(ref r))
            {
                return State.ElementName;
            }
            else if (ParseDollarSign(ref r))

View on GitHub (pinned to 11c5427268)

Solutions

  1. Inspect the binding path string and remove the trailing '.' or '?.', or add the missing member name after it.
  2. If building paths dynamically, trim trailing accessor operators before passing to the binding system.
  3. Search the XAML or C# source for the exact binding string reported in the Column property of the exception and verify every '.' or '?.' is followed by an identifier.

Example fix

<!-- before -->
<TextBox Text="{Binding Foo.}" />

<!-- after -->
<TextBox Text="{Binding Foo.Bar}" />
Defensive patterns

Strategy: validation

Validate before calling

// Validate that a binding path string does not end with a member-access operator
static void ValidateBindingPath(string path)
{
    if (path.EndsWith('.') || path.EndsWith("?."))
        throw new ArgumentException(
            $"Binding path '{path}' ends with a member-access operator; a member name is required after '.' or '?.'");
}

Try / catch

try
{
    var binding = new Binding(path);
}
catch (ExpressionParseException ex)
{
    // ex.Column points to the position of the trailing dot
    logger.LogError($"Invalid binding path at column {ex.Column}: {ex.Message}");
}

Prevention

When it happens

Trigger: The binding expression string ends with '.' (e.g. 'Foo.') or '?.' (e.g. 'Foo?.') with no identifier following the operator. Also triggered when dynamic string concatenation appends a trailing dot conditionally, such as $"{path}." where path is the last segment.

Common situations: Incomplete auto-complete in a XAML Binding Path attribute leaving a trailing dot; building binding paths programmatically via StringBuilder or interpolation that conditionally appends '.' on the last segment; copy-paste errors where a property name after the dot was accidentally deleted.

Related errors


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