dotnet/maui · error · BuildException
XC0003
XC0003
Error message
Missing mandatory property "{0}" on "{1}". What it means
XC0003 PropertyMissing thrown by the DataTemplateExtension compiled markup extension when the required 'TypeName' property is absent. The extension first checks node.Properties for a 'TypeName' key, then falls back to the first collection item. If neither yields a ValueNode (e.g. the property is missing and there are no collection items, or the item is an element node rather than a value), the build fails.
Source
Thrown at src/Controls/src/Build.Tasks/CompiledMarkupExtensions/DataTemplateExtension.cs:23
using Mono.Cecil;
using Mono.Cecil.Cil;
using static Mono.Cecil.Cil.Instruction;
using static Mono.Cecil.Cil.OpCodes;
namespace Microsoft.Maui.Controls.Build.Tasks
{
class DataTemplateExtension : ICompiledMarkupExtension
{
public IEnumerable<Instruction> ProvideValue(ElementNode node, ModuleDefinition module, ILContext context, out TypeReference typeRef)
{
typeRef = module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "DataTemplate"));
var name = new XmlName("", "TypeName");
if (!node.Properties.TryGetValue(name, out INode typeNameNode) && node.CollectionItems.Any())
typeNameNode = node.CollectionItems[0];
if (typeNameNode is not ValueNode valueNode)
throw new BuildException(BuildExceptionCode.PropertyMissing, node as IXmlLineInfo, null, "TypeName", typeof(Microsoft.Maui.Controls.Xaml.DataTemplateExtension));
var contentTypeRef = module.ImportReference(XmlTypeExtensions.GetTypeReference(context.Cache, valueNode.Value as string, module, node as BaseNode))
?? throw new BuildException(BuildExceptionCode.TypeResolution, node as IXmlLineInfo, null, valueNode.Value);
var dataTemplateCtor = module.ImportCtorReference(context.Cache, typeRef, new[] { module.ImportReference(context.Cache, ("mscorlib", "System", "Type")) });
return [
Create(Ldtoken, module.ImportReference(contentTypeRef)),
Create(Call, module.ImportMethodReference(context.Cache, ("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)),
Create(Newobj, dataTemplateCtor),
];
}
}
}
View on GitHub (pinned to f377ff1c5e)
Solutions
- Add the TypeName attribute to the DataTemplate extension usage, e.g. {DataTemplate TypeName='local:MyView'}.
- Ensure the TypeName value is a simple string (ValueNode) representing a type reference, not a nested element.
- If using inline syntax, ensure the first child item is a value node with the type name.
Example fix
<!-- before --> <DataTemplate /> <!-- after --> <DataTemplate TypeName="local:MyItemView" />
Defensive patterns
Strategy: validation
Validate before calling
// Validate that a DataTemplate extension node has a TypeName property or collection item
static bool HasTypeNameValue(IDictionary<XmlName, INode> properties, IList<INode> collectionItems)
=> (properties.TryGetValue(new XmlName("", "TypeName"), out var node) && node is ValueNode)
|| (collectionItems.Any() && collectionItems[0] is ValueNode); Prevention
- Always include TypeName when using the {DataTemplate} compiled markup extension.
- Provide TypeName as a simple string attribute value, not a nested element.
- Distinguish this compiled extension from the runtime DataTemplate(Type) constructor.
When it happens
Trigger: Using {DataTemplate} markup extension without specifying TypeName, or providing a non-value node where TypeName is expected. The extension requires either TypeName="MyType" as an attribute or a inline value as the first child item.
Common situations: Forgetting to include TypeName when using the {DataTemplate} extension. Providing a complex element instead of a simple type-name string. Confusing this compiled extension with the runtime DataTemplate API which accepts a Type object directly.
Related errors
AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13).
Data as JSON: /api/errors/9bbf098618889f70.
Report an issue: GitHub.