dotnet/maui · error · BuildException
XC0125
XC0125
Error message
"A resource with the key "{0}" is already present in the ResourceDictionary. What it means
Raised by the XAML compiler (Build.Tasks) when two resources inside the same ResourceDictionary declare the same x:Key. The build task keeps a name set via GetResourceNamesInUse(parent) and rejects any key that already appears in it, so the XAML cannot compile until the collision is removed.
Source
Thrown at src/Controls/src/Build.Tasks/SetPropertiesVisitor.cs:1936
return CanAddToResourceDictionary(parent, propertyType, elementNode, lineInfo, context);
}
static bool CanAddToResourceDictionary(VariableDefinition parent, TypeReference collectionType, ElementNode node, IXmlLineInfo lineInfo, ILContext context)
{
if (parent is null)
return false;
if (collectionType.FullName != "Microsoft.Maui.Controls.ResourceDictionary"
&& !collectionType.InheritsFromOrImplements(context.Cache, context.Module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ResourceDictionary"))))
return false;
if (node.Properties.TryGetValue(XmlName.xKey, out INode value))
{
var valueNode = value as ValueNode ?? throw new BuildException(XKeyNotLiteral, lineInfo, null);
var key = valueNode.Value as string;
var names = context.Cache.GetResourceNamesInUse(parent);
if (names.Contains(key))
throw new BuildException(ResourceDictDuplicateKey, lineInfo, null, key);
return true;
}
//is there a RD.Add() overrides that accepts this ?
var nodeTypeRef = context.Variables[node].VariableType;
var module = context.Body.Method.Module;
if (module.ImportMethodReference(context.Cache,
module.GetTypeDefinition(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ResourceDictionary")),
methodName: "Add",
parameterTypes: [nodeTypeRef]) != null)
return true;
throw new BuildException(ResourceDictMissingKey, lineInfo, null);
}
static IEnumerable<Instruction> Add(VariableDefinition parent, XmlName propertyName, INode node, IXmlLineInfo iXmlLineInfo, ILContext context)
{
var module = context.Body.Method.Module;
var elementNode = node as ElementNode;View on GitHub (pinned to f377ff1c5e)
Solutions
- Search the whole XAML file (and any MergedDictionaries) for the duplicate x:Key and rename one of the two occurrences to a unique value.
- If the duplicate comes from a merged dictionary, override it intentionally with MergedWith/Source semantics or remove it from the source dictionary instead of redeclaring.
- Use a unique prefix per feature area (e.g. 'LoginPrimaryButton') to avoid accidental collisions as dictionaries grow.
Example fix
<!-- before -->
<ResourceDictionary>
<x:String x:Key="Greeting">Hello</x:String>
<x:String x:Key="Greeting">Hi</x:String>
</ResourceDictionary>
<!-- after -->
<ResourceDictionary>
<x:String x:Key="Greeting">Hello</x:String>
<x:String x:Key="GreetingAlt">Hi</x:String>
</ResourceDictionary> Defensive patterns
Strategy: validation
Validate before calling
// Before shipping XAML, assert every x:Key in a ResourceDictionary is unique.
// Pseudo: gather all x:Key literal strings per RD scope and assert no duplicates.
static void AssertUniqueKeys(IEnumerable<string> keys)
{
var dup = keys.GroupBy(k => k).Where(g => g.Count() > 1).Select(g => g.Key);
if (dup.Any()) throw new InvalidOperationException("Duplicate keys: " + string.Join(", ", dup));
} Prevention
- Run the XAML compiler (XC0125) as part of CI so duplicate keys fail the build before runtime.
- Adopt a key-naming convention per feature area to avoid accidental collisions across merged dictionaries.
- When merging ResourceDictionaries, grep for the new keys against the destination before merging.
When it happens
Trigger: The SetPropertiesVisitor sees a node whose parent collection is (or inherits from) Microsoft.Maui.Controls.ResourceDictionary, the node carries an x:Key whose string value is already present in context.Cache.GetResourceNamesInUse(parent), and the duplicate key throw fires.
Common situations: Copying a Style/Color/OnPlatform block and forgetting to rename its x:Key; merging MergedDictionaries that both define 'DefaultStyle'; refactoring resources between App.xaml and page-level dictionaries where the same key leaks in.
Related errors
AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13).
Data as JSON: /api/errors/df6faa13f515b9dd.
Report an issue: GitHub.