dotnet/maui · error · BuildException

XC0003

XC0003

Error message

Missing mandatory property "{0}" on "{1}".

What it means

Thrown by the compiled x:Type extension when the TypeName property (or the single inline collection item) is not a string literal ValueNode. x:Type needs a concrete type name string to import and emit a Type token; a missing or non-literal value makes emission impossible.

Source

Thrown at src/Controls/src/Build.Tasks/CompiledMarkupExtensions/TypeExtension.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 TypeExtension : ICompiledMarkupExtension
	{
		public IEnumerable<Instruction> ProvideValue(ElementNode node, ModuleDefinition module, ILContext context, out TypeReference memberRef)
		{
			memberRef = module.ImportReference(context.Cache, ("mscorlib", "System", "Type"));
			var name = new XmlName("", "TypeName");

			if (!node.Properties.TryGetValue(name, out INode typeNameNode) && node.CollectionItems.Any())
				typeNameNode = node.CollectionItems[0];

			if (!(typeNameNode is ValueNode valueNode))
				throw new BuildException(BuildExceptionCode.PropertyMissing, node as IXmlLineInfo, null, "TypeName", typeof(Microsoft.Maui.Controls.Xaml.TypeExtension));

			if (!node.Properties.ContainsKey(name))
			{
				node.Properties[name] = typeNameNode;
				node.CollectionItems.Clear();
			}

			var typeref = module.ImportReference(XmlTypeExtensions.GetTypeReference(context.Cache, valueNode.Value as string, module, node as BaseNode));

			context.TypeExtensions[node] = typeref ?? throw new BuildException(BuildExceptionCode.TypeResolution, node as IXmlLineInfo, null, valueNode.Value);

			return new List<Instruction> {
				Create(Ldtoken, module.ImportReference(typeref)),
				Create(Call, module.ImportMethodReference(context.Cache, ("mscorlib", "System", "Type"),
														  methodName: "GetTypeFromHandle",
														  parameterTypes: [("mscorlib", "System", "RuntimeTypeHandle")],
														  isStatic: true)),
			};

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Provide TypeName="MyNamespace.MyType" as an attribute, or put the type name as inline text content.
  2. Ensure the xmlns prefix for the type's namespace is declared and used, e.g. TypeName="local:MyView".
  3. Verify the value is a plain string literal, not a nested element/marker.
  4. If the type must be dynamic, do not use x:Type in compiled XAML; resolve it in code-behind.

Example fix

// before
<DataTemplate>
  <x:Type />
</DataTemplate>
// after
<DataTemplate>
  <x:Type TypeName="local:MyView" />
</DataTemplate>
Defensive patterns

Strategy: validation

Validate before calling

// Ensure x:Type has a literal TypeName
static bool XTypeHasLiteralTypeName(XElement el) =>
    el.Attribute("TypeName") is { Value: { Length: > 0 } v }
    || (!el.Elements().Any() && !string.IsNullOrWhiteSpace(el.Value));

Prevention

When it happens

Trigger: Using <x:Type /> with no TypeName attribute and no inline text; binding TypeName to another markup extension or element node instead of a literal; whitespace-only content that fails the ValueNode cast.

Common situations: Authoring a DataTemplate or Style TargetType via x:Type and forgetting the type name; attempting to compute the type dynamically at build time; malformed XAML where the closing tag swallows the text.

Related errors


AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13). Data as JSON: /api/errors/8ce639aced799e1d. Report an issue: GitHub.