AvaloniaUI/Avalonia · error · ExpressionParseException

Expected ')'.

Error message

Expected ')'.

What it means

Thrown by ParseAttachedProperty after the full '(Owner.Property' path has been parsed (type name, dot, and property name all consumed) but the closing ')' is missing from the string or a non-')' character appears where ')' is expected. Avalonia requires balanced parentheses around every attached-property or type-cast expression in the binding mini-language.

Source

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

                nodes.Add(new TypeCastNode() { Namespace = ns, TypeName = owner });
                return State.AfterMember;
            }

            if (r.End || !r.TakeIf('.'))
            {
                throw new ExpressionParseException(r.Position, "Invalid attached property name.");
            }

            var name = r.ParseIdentifier();

            if (name.Length == 0)
            {
                throw new ExpressionParseException(r.Position, "Attached Property name expected after '.'.");
            }

            if (r.End || !r.TakeIf(')'))
            {
                throw new ExpressionParseException(r.Position, "Expected ')'.");
            }

            nodes.Add(new AttachedPropertyNameNode
            {
                AcceptsNull = acceptsNull,
                Namespace = ns,
                TypeName = owner,
                PropertyName = name.ToString()
            });
            return State.AfterMember;
        }

        private static State ParseIndexer(ref CharacterReader r, List<INode> nodes)
        {
            var args = r.ParseArguments('[', ']');

            if (args.Count == 0)
            {

View on GitHub (pinned to 11c5427268)

Solutions

  1. Add the missing ')' at the end of the attached-property expression.
  2. Check that the total open-paren and close-paren counts in the binding path are balanced.
  3. Use the Column property from the exception to locate where ')' was expected.

Example fix

<!-- before: missing closing ')' -->
<TextBox Text="{Binding (Grid.Row}" />

<!-- after: closing ')' added -->
<TextBox Text="{Binding (Grid.Row)}" />
Defensive patterns

Strategy: validation

Validate before calling

// Validate that parentheses are balanced in a binding path
static void ValidateBalancedParens(string path)
{
    int depth = 0;
    for (int i = 0; i < path.Length; i++)
    {
        if (path[i] == '(') depth++;
        else if (path[i] == ')') depth--;
        if (depth < 0)
            throw new ArgumentException($"Unbalanced ')' at position {i}");
    }
    if (depth != 0)
        throw new ArgumentException($"Unbalanced '(' — {depth} unclosed paren group(s)");
}

Try / catch

try
{
    var binding = new Binding(path);
}
catch (ExpressionParseException ex) when (ex.Message.Contains("Expected ')'"))
{
    logger.LogError($"Missing ')' at column {ex.Column} in binding path");
}

Prevention

When it happens

Trigger: Writing '(Grid.Row' at end of string, or '(Grid.Row;More' where ')' is expected but a different character is present. The parser has consumed the property name via ParseIdentifier and now checks r.TakeIf(')') which returns false.

Common situations: Truncated binding string where the closing paren was cut off during copy-paste; building attached-property paths dynamically and forgetting to append ')'; mixing up the compact '(Type.Property)' syntax with the full XAML '{Binding Path=(Type.Property)}' wrapper and losing a paren.

Related errors


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