dotnet/maui · error · BuildException
XC0128
XC0128
Error message
A key is required in {StaticResource}. What it means
Thrown by the compiled {StaticResource} provider when no Key can be found on the markup node. StaticResource requires a Key attribute (or a single collection item used as the key); if neither is present, keyNode is null or not a ValueNode and the build fails.
Source
Thrown at src/Controls/src/Build.Tasks/CompiledMarkupExtensions/StaticResourceExtension.cs:24
using Mono.Cecil.Cil;
using static Mono.Cecil.Cil.Instruction;
using static Mono.Cecil.Cil.OpCodes;
namespace Microsoft.Maui.Controls.Build.Tasks
{
//yes, this is a ICompiledMarkupExtension, but declared as ICompiledValueProvider so it's evaluated later (in SetPropertyValue, not CreateObject)
class StaticResourceExtension : ICompiledValueProvider
{
public IEnumerable<Instruction> ProvideValue(VariableDefinitionReference vardefref, ModuleDefinition module, BaseNode node, ILContext context)
{
var name = new XmlName("", "Key");
var eNode = node as ElementNode;
if (!eNode.Properties.TryGetValue(name, out INode keyNode) && eNode.CollectionItems.Any())
keyNode = eNode.CollectionItems[0];
if (!(keyNode is ValueNode keyValueNode))
throw new BuildException(BuildExceptionCode.StaticResourceSyntax, eNode as IXmlLineInfo, null, null);
var n = eNode;
while (n != null)
{
if (n.Properties.TryGetValue(new XmlName(XamlParser.MauiUri, "Resources"), out var resourcesNode))
{
//single resource in <Resources>
if (resourcesNode is ElementNode irn
&& irn.Properties.TryGetValue(XmlName.xKey, out INode xKeyNode)
&& context.Variables.TryGetValue(irn, out VariableDefinition value)
&& xKeyNode is ValueNode xKeyValueNode
&& xKeyValueNode.Value as string == keyValueNode.Value as string)
{
if (value.VariableType.FullName == "System.String")
{
foreach (var instruction in TryConvert(irn.CollectionItems[0] as ValueNode, eNode, vardefref, module, context))
yield return instruction;
yield break;View on GitHub (pinned to f377ff1c5e)
Solutions
- Add the Key attribute with the resource name: {StaticResource Key="MyBrush"} or the shorthand form.
- Ensure the Key is a literal string value, not a nested markup expression.
- Confirm the matching resource with that key exists in a reachable ResourceDictionary.
- If you need runtime key resolution, switch off XAML compilation for that binding (x:CompileBindings) or use a code-behind lookup.
Example fix
// before
<ContentPage.Resources>
<!-- resource defined -->
</ContentPage.Resources>
<Label Text="{StaticResource}" />
// after
<Label Text="{StaticResource Key=GreetingTemplate}" /> Defensive patterns
Strategy: validation
Validate before calling
// Lint: every {StaticResource} must carry a literal Key
static bool StaticResourceHasKey(string expr) {
if (!expr.StartsWith("{StaticResource")) return true; // not our concern
return expr.Contains("Key=") ||
Regex.IsMatch(expr, @"\{StaticResource\s+([A-Za-z_][\w]*)");
} Prevention
- Always specify the resource key explicitly in {StaticResource Key=...}.
- Keep resource keys in a constants file to avoid mismatches.
- Confirm the key exists in a reachable ResourceDictionary before referencing it.
When it happens
Trigger: Writing <StaticResource /> with no Key attribute and no inline content; binding the Key to a non-literal node (e.g. another markup extension) so keyNode is not a ValueNode; referencing {StaticResource} where the resource key is dynamically computed.
Common situations: Forgetting to specify which resource to fetch; confusing StaticResource with DynamicResource syntax; copy-paste leaving an empty {StaticResource}; trying to key on a binding expression which the compiled form cannot evaluate at build time.
Related errors
AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13).
Data as JSON: /api/errors/393658520c844a6f.
Report an issue: GitHub.