dotnet/maui · error · BuildException

XC0066

XC0066

Error message

Invalid Xaml "Protected Xmlns {xmlNamespace}. Can't add assembly {assemblyName}."

What it means

Raised when an assembly tries to register itself into one of the protected XML namespaces (the MAUI uri or the XAML 2009 uri) via a XmlnsDefinitionAttribute, but its assembly name does not begin with Microsoft/System/mscorlib. Those namespaces are reserved for the framework, so the build task rejects the registration as invalid XAML.

Source

Thrown at src/Controls/src/Build.Tasks/XmlTypeExtensions.cs:62

						xmlnsDefinitions.Add(attribute);
					}
			}

			return xmlnsDefinitions;
		}
		static void ValidateProtectedXmlns(string xmlNamespace, string assemblyName)
		{
			//maui, and x: xmlns are protected
			if (xmlNamespace != XamlParser.MauiUri && xmlNamespace != XamlParser.X2009Uri)
				return;

			//we know thos assemblies, they are fine in maui or x xmlns
			if (assemblyName.StartsWith("Microsoft", StringComparison.OrdinalIgnoreCase)
				|| assemblyName.StartsWith("System", StringComparison.OrdinalIgnoreCase)
				|| assemblyName.StartsWith("mscorlib", StringComparison.OrdinalIgnoreCase))
				return;

			throw new BuildException(BuildExceptionCode.InvalidXaml, null, null,
				$"Protected Xmlns {xmlNamespace}. Can't add assembly {assemblyName}.");

		}
		static void GatherXmlnsDefinitionAttributes(List<XmlnsDefinitionAttribute> xmlnsDefinitions, AssemblyDefinition asmDef, AssemblyDefinition currentAssembly)
		{
			foreach (var ca in asmDef.CustomAttributes)
			{
				if (ca.AttributeType.FullName == _xmlnsDefinitionName)
				{
					var attr = GetXmlnsDefinition(ca, asmDef);
					//only add globalxmlns definition from the current assembly
					if (attr.XmlNamespace == XamlParser.MauiGlobalUri
						&& asmDef != currentAssembly)
						continue;
					ValidateProtectedXmlns(attr.XmlNamespace, attr.AssemblyName);
					xmlnsDefinitions.Add(attr);
				}
			}

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Change the XmlnsDefinition attribute to use your own custom uri, e.g. 'http://mycompany.com/schemas/mylib'.
  2. If you only want a clr-namespace shortcut, register under an unreserved uri and reference the clr-namespace directly in XAML.
  3. Remove the XmlnsDefinition attribute entirely if you do not need a custom xmlns prefix for your controls.

Example fix

// before
[assembly: XmlnsDefinition("http://schemas.microsoft.com/dotnet/2021/maui", "MyLib.Controls")]
// after
[assembly: XmlnsDefinition("http://mycompany.com/schemas/mylib", "MyLib.Controls")]
Defensive patterns

Strategy: validation

Validate before calling

// Assembly-level guard: never register a third-party assembly into a reserved xmlns.
static readonly HashSet<string> Reserved = new() { XamlParser.MauiUri, XamlParser.X2009Uri };
static string SafeXmlns(string desired, string assemblyName)
    => Reserved.Contains(desired) && !assemblyName.StartsWith("Microsoft", StringComparison.OrdinalIgnoreCase)
        ? $"http://{assemblyName.ToLowerInvariant()}.local/schemas"
        : desired;

Prevention

When it happens

Trigger: ValidateProtectedXmlns is called with xmlNamespace equal to XamlParser.MauiUri or XamlParser.X2009Uri and an assemblyName that does not StartsWith Microsoft/System/mscorlib (case-insensitive), reaching the final throw.

Common situations: A third-party library copies a Maui sample assembly attribute and reuses 'http://schemas.microsoft.com/dotnet/2021/maui' as its XmlnsDefinition; a library targets the XAML 2009 namespace intentionally; a generated assembly accidentally emits the reserved uri.

Related errors


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