{"record":{"id":"efc4a6e4313dc5c3","repo":"AvaloniaUI/Avalonia","slug":"unexpected-end-of-expression","errorCode":null,"errorMessage":"Unexpected end of expression.","messagePattern":"Unexpected end of expression\\.","errorType":"validation","errorClass":"ExpressionParseException","httpStatus":null,"severity":"error","filePath":"src/Avalonia.Base/Data/Core/Parsers/BindingExpressionGrammar.cs","lineNumber":103,"sourceCode":"                        state = ParseElementName(ref r, nodes);\n                        mode = SourceMode.Control;\n                        break;\n\n                    case State.RelativeSource:\n                        state = ParseRelativeSource(ref r, nodes);\n                        mode = SourceMode.Control;\n                        break;\n                }\n            }\n\n            if (!r.End)\n            {\n                throw new ExpressionParseException(r.Position, \"Expected end of expression.\");\n            }\n\n            if (state is State.BeforeMember or State.BeforeMemberNullable)\n            {\n                throw new ExpressionParseException(r.Position, \"Unexpected end of expression.\");\n            }\n\n            return mode;\n        }\n\n        private static State ParseStart(ref CharacterReader r, IList<INode> nodes)\n        {\n            if (ParseNot(ref r))\n            {\n                nodes.Add(new NotNode());\n                return State.Start;\n            }\n\n            else if (ParseSharp(ref r))\n            {\n                return State.ElementName;\n            }\n            else if (ParseDollarSign(ref r))","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Avalonia.Base/Data/Core/Parsers/BindingExpressionGrammar.cs#L85-L121","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the binding path string and remove the trailing '.' or '?.', or add the missing member name after it.","If building paths dynamically, trim trailing accessor operators before passing to the binding system.","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."],"exampleFix":"<!-- before -->\n<TextBox Text=\"{Binding Foo.}\" />\n\n<!-- after -->\n<TextBox Text=\"{Binding Foo.Bar}\" />","handlingStrategy":"validation","validationCode":"// Validate that a binding path string does not end with a member-access operator\nstatic void ValidateBindingPath(string path)\n{\n    if (path.EndsWith('.') || path.EndsWith(\"?.\"))\n        throw new ArgumentException(\n            $\"Binding path '{path}' ends with a member-access operator; a member name is required after '.' or '?.'\");\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    var binding = new Binding(path);\n}\ncatch (ExpressionParseException ex)\n{\n    // ex.Column points to the position of the trailing dot\n    logger.LogError($\"Invalid binding path at column {ex.Column}: {ex.Message}\");\n}","preventionTips":["Run all binding paths through a unit test that exercises the parser at design time.","Use source generators or XAML compilation to catch invalid paths at build time rather than runtime.","Avoid building binding path strings via concatenation; if you must, trim trailing '.' and '?.' characters."],"tags":["avalonia","binding","xaml","binding-expression","parser","syntax-error"],"backgroundTag":null,"analyzedSha":"11c542726898ae954a1ef668c65ec79ec92ab17d","analyzedAt":"2026-08-13T11:57:40.261Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}