{"record":{"id":"b4d7c5881825aa67","repo":"dotnet/maui","slug":"xc0060","errorCode":"XC0060","errorMessage":"Markup expression not closed.","messagePattern":"Markup expression not closed\\.","errorType":"exception","errorClass":"BuildException","httpStatus":null,"severity":"error","filePath":"src/Controls/src/Build.Tasks/ExpandMarkupsVisitor.cs","lineNumber":88,"sourceCode":"\t\t\t\treturn false;\n\t\t\tforeach (var kvp in parentElement.Properties)\n\t\t\t{\n\t\t\t\tif (kvp.Value != node)\n\t\t\t\t\tcontinue;\n\t\t\t\tname = kvp.Key;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\tstatic INode ParseExpression(ref string expression, ILContext context, IXmlNamespaceResolver nsResolver,\n\t\t\tIXmlLineInfo xmlLineInfo)\n\t\t{\n\t\t\tif (expression.StartsWith(\"{}\", StringComparison.Ordinal))\n\t\t\t\treturn new ValueNode(expression.Substring(2), null);\n\n\t\t\tif (expression[expression.Length - 1] != '}')\n\t\t\t\tthrow new BuildException(BuildExceptionCode.MarkupNotClosed, xmlLineInfo, null);\n\n\t\t\tif (!MarkupExpressionParser.MatchMarkup(out var match, expression, out var len))\n\t\t\t\tthrow new BuildException(BuildExceptionCode.MarkupParsingFailed, xmlLineInfo, null);\n\t\t\texpression = expression.Substring(len).TrimStart();\n\t\t\tif (expression.Length == 0)\n\t\t\t\tthrow new BuildException(BuildExceptionCode.MarkupNotClosed, xmlLineInfo, null);\n\n\t\t\tvar provider = new XamlServiceProvider(null, null);\n\t\t\tprovider.Add(typeof(ILContextProvider), new ILContextProvider(context));\n\t\t\tprovider.Add(typeof(IXmlNamespaceResolver), nsResolver);\n\t\t\tprovider.Add(typeof(IXmlLineInfoProvider), new XmlLineInfoProvider(xmlLineInfo));\n\n\t\t\treturn new MarkupExpansionParser().Parse(match, ref expression, provider);\n\t\t}\n\n\t\tclass ILContextProvider(ILContext context)\n\t\t{\n\t\t\tpublic ILContext Context { get; } = context;","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/dotnet/maui/blob/f377ff1c5ee04d334d8a925f50c83a6b7afddf03/src/Controls/src/Build.Tasks/ExpandMarkupsVisitor.cs#L70-L106","documentation":"Thrown by ExpandMarkupsVisitor.ParseExpression when a markup expression string's last character is not '}'. Every XAML markup extension must be wrapped in { ... }; the compiler checks the closing brace first before attempting to parse.","triggerScenarios":"Writing {Binding Path=Foo (missing closing brace); a stray truncation like Text=\"{x:Static\"; an unterminated expression from a merge conflict or partial edit.","commonSituations":"Manual editing that deletes the trailing brace; templated/string-generated XAML that omits the brace; copy-paste that cut off the end.","solutions":["Ensure the expression ends with '}', e.g. \"{Binding Path=Foo}\".","Use the XAML editor's validation/intellisense to auto-close braces.","Search the file for '{' without a matching '}' to locate the broken expression."],"exampleFix":"// before\n<Label Text=\"{Binding Title\" />\n// after\n<Label Text=\"{Binding Title}\" />","handlingStrategy":"validation","validationCode":"// Lint: every '{' markup expression must end with '}'\nstatic bool MarkupIsClosed(string value) {\n    if (!value.Contains(\"{\" + \"\") || value.StartsWith(\"{}\")) return true;\n    return value.TrimEnd().EndsWith(\"}\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always close markup expressions with '}'.","Use IDE intellisense to auto-close braces.","Lint XAML for unmatched braces in CI."],"tags":["xaml","xamlc","markup-extension","syntax","build-time"],"backgroundTag":null,"analyzedSha":"f377ff1c5ee04d334d8a925f50c83a6b7afddf03","analyzedAt":"2026-08-13T14:26:18.069Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}