dotnet/maui · error · BuildException
XC0061
XC0061
Error message
Error while parsing markup expression.
What it means
Thrown when MarkupExpressionParser.MatchMarkup cannot recognize the leading token of a markup expression as a valid markup extension name. After confirming the closing brace, the compiler tries to match the extension identifier; failure means the syntax does not start with a known markup name pattern.
Source
Thrown at src/Controls/src/Build.Tasks/ExpandMarkupsVisitor.cs:91
if (kvp.Value != node)
continue;
name = kvp.Key;
return true;
}
return false;
}
static INode ParseExpression(ref string expression, ILContext context, IXmlNamespaceResolver nsResolver,
IXmlLineInfo xmlLineInfo)
{
if (expression.StartsWith("{}", StringComparison.Ordinal))
return new ValueNode(expression.Substring(2), null);
if (expression[expression.Length - 1] != '}')
throw new BuildException(BuildExceptionCode.MarkupNotClosed, xmlLineInfo, null);
if (!MarkupExpressionParser.MatchMarkup(out var match, expression, out var len))
throw new BuildException(BuildExceptionCode.MarkupParsingFailed, xmlLineInfo, null);
expression = expression.Substring(len).TrimStart();
if (expression.Length == 0)
throw new BuildException(BuildExceptionCode.MarkupNotClosed, xmlLineInfo, null);
var provider = new XamlServiceProvider(null, null);
provider.Add(typeof(ILContextProvider), new ILContextProvider(context));
provider.Add(typeof(IXmlNamespaceResolver), nsResolver);
provider.Add(typeof(IXmlLineInfoProvider), new XmlLineInfoProvider(xmlLineInfo));
return new MarkupExpansionParser().Parse(match, ref expression, provider);
}
class ILContextProvider(ILContext context)
{
public ILContext Context { get; } = context;
}
class MarkupExpansionParser : MarkupExpressionParser, IExpressionParser<INode>View on GitHub (pinned to f377ff1c5e)
Solutions
- Escape literal braces with the '{} ' prefix, e.g. Content="{}{not a binding}".
- If intending a markup extension, start with a valid name: '{Binding ...}', '{x:Static ...}', etc.
- Remove stray '{' characters from attribute values.
Example fix
// before
<Label Text="{some literal text}" />
// after
<Label Text="{}{some literal text}" /> Defensive patterns
Strategy: validation
Validate before calling
// Lint: a '{' must be followed by a valid markup name or escaped with '{}'
static readonly Regex MarkupName = new(@"^\{([A-Za-z_][\w\.]*:?[A-Za-z_][\w\.]*)");
static bool MarkupStartsValid(string value) =>
value.StartsWith("{}") || MarkupName.IsMatch(value) || !value.StartsWith("{"); Prevention
- Escape literal braces with the '{} ' prefix.
- Begin real markup with a known extension name like Binding or x:Static.
When it happens
Trigger: An expression that begins with '{' but the next token is not a valid markup name (e.g. '{123}' or '{ }'); a malformed/empty markup name; stray '{' used as literal text without the '{}' escape prefix.
Common situations: Using '{' literally in text without escaping with '{}'; whitespace or operators right after '{'; tooling that injects a brace for interpolation.
Related errors
AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13).
Data as JSON: /api/errors/0e1db63639250fe2.
Report an issue: GitHub.