dotnet/wpf · error · XamlSchemaException

SR.Format(SR.TooManyAttributes, DeclaringType.Name, Name…

Error message

SR.Format(SR.TooManyAttributes, DeclaringType.Name, Name, attrType.Name)

What it means

ClrProperty.LookupCustomAttribute throws XamlSchemaException when more than one attribute of the requested type (attrType) is found on the property. The XAML schema model assumes attribute types used for single-value lookups are used at most once per property (AllowMultiple=false semantics). Multiple instances make the intended value ambiguous, so the schema refuses to guess.

Solutions

  1. Remove the duplicate attribute so only one instance of attrType remains on the property.
  2. If multiple instances are intentional, stop relying on the single-attribute lookup API and read all instances with GetCustomAttributes yourself.
  3. Mark the attribute type AllowMultiple=false and fix the declaration site flagged by the exception message (declaring type and property name are in the message).

Example fix

// before
[XamlDeferLoad("A", "B")]
[XamlDeferLoad("C", "D")]
public Foo Bar { get; set; }

// after
[XamlDeferLoad("A", "B")]
public Foo Bar { get; set; }
Defensive patterns

Strategy: validation

Validate before calling

// before schema use: assert single attribute per property
var attrs = prop.GetCustomAttributes(attrType, inherit: true).ToArray();
if (attrs.Length > 1)
    throw new InvalidOperationException($"{prop.DeclaringType.Name}.{prop.Name} has {attrs.Length} {attrType.Name}; expected at most 1");

Type guard

bool HasSingle<TAttr>(MemberInfo m) => m.GetCustomAttributes(typeof(TAttr), true).Length == 1;

Try / catch

try { var value = schemaProperty.Attr<TAttr>(); }
catch (XamlSchemaException ex) { log(ex.Message); /* fall back to manual attribute scan */ }

Prevention

When it happens

Trigger: Calling attr()/LookupCustomAttribute (directly or via XamlType/XamlMember schema APIs) on a ClrProperty whose reflected CLR property has two or more attributes of the same type applied, e.g. two [XamlDeferLoad] or two duplicate custom metadata attributes on one property.

Common situations: Copy-pasting an attribute line twice on a property; a custom metadata attribute declared AllowMultiple=true that System.Xaml treats as single-use; assembly version merges duplicating attributes via MetadataUpdate or IL weaving/aspect-weaving tools re-applying attributes.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/7c89c2e5994fdc94. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/ClrProperty.cs:307

        // ==============================================

        protected virtual Type LookupSystemTypeOfProperty()
        {
            return ClrBindingPropertyInfo.PropertyType;
        }

        private object LookupCustomAttribute(Type attrType)
        {
            object[] objs = LookupCustomAttributes(attrType);
            if (objs.Length == 0)
            {
                return null;
            }
            if (objs.Length > 1)
            {
                string message = SR.Format(SR.TooManyAttributes, DeclaringType.Name, Name, attrType.Name);
                throw new XamlSchemaException(message);
            }
            return objs[0];
        }

        protected virtual object[] LookupCustomAttributes(Type attrType)
        {
            return ClrBindingPropertyInfo.GetCustomAttributes(attrType, true);
        }

        // ==============================================

        private bool LookupIsBrowsable()
        {
            Object attr = LookupCustomAttribute(typeof(EditorBrowsableAttribute));
            if (null != attr)
            {
                EditorBrowsableAttribute eba = (EditorBrowsableAttribute)attr;
                if (eba.State == EditorBrowsableState.Never)

View on GitHub (pinned to 81131a70a4)