dotnet/wpf · error · XamlSchemaException
SR.Format(SR.AmbiguousCollectionItemType, type)
Error message
SR.Format(SR.AmbiguousCollectionItemType, type)
What it means
CollectionReflector.LookupAddMethod throws XamlSchemaException when a type is detected as a Collection (implements ICollection<T> in a way that should yield an Add method) but TryGetCollectionAdder cannot determine a unique Add method / item type. The collection's item type is ambiguous, so XAML cannot know what element type to construct for children.
Solutions
- Make the collection implement exactly one closed ICollection<T> (remove extra generic collection interfaces).
- Provide an explicit public Add(T) method matching a single item type so reflection can resolve it.
- Wrap the multi-interface collection in a dedicated class exposing one item type, and use that in XAML.
Example fix
// before
class Bag : ICollection<string>, ICollection<int> { }
// after
class StringBag : ICollection<string> { } Defensive patterns
Strategy: type-guard
Validate before calling
// ensure exactly one closed ICollection<T>
var i_coll = typeof(TCollection).GetInterfaces()
.Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICollection<>)).ToList();
if (i_coll.Count != 1) throw new InvalidOperationException($"{typeof(TCollection)} must implement exactly one ICollection<T>"); Type guard
static bool HasUniqueCollectionItem<T>(T c) where T : ICollection<string> => c.GetType().GetInterfaces().Count(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICollection<>)) == 1;
Try / catch
try { result = CollectionReflector.LookupAddMethod(type, kind); }
catch (XamlSchemaException ex) { log($"Collection {type} has ambiguous item type: {ex.Message}"); } Prevention
- Implement only one closed ICollection<T> per XAML-visible collection
- Provide an explicit public Add(T) method
- Avoid multiple generic collection interfaces on one class
- Wrap multi-interface collections for XAML use
When it happens
Trigger: Looking up the add method for a XamlCollectionKind.Collection type that implements multiple closed ICollection<T> interfaces (e.g. ICollection<string> and ICollection<int>) or otherwise offers no single unambiguous Add signature.
Common situations: Custom collection classes implementing ICollection<T> for several item types; a class changed to add a second generic collection interface after an upgrade; generic types used without a concrete closed type in XAML.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- SR.Format(SR.AmbiguousDictionaryItemType, type)
- SR.MarkupExtensionDynamicOrBindingInCollection
- SR.NoAddMethodFound
- SR.XamlXmlWriterIsObjectFromMemberSetForArraysOrNonCollectio…
- throw new NotSupportedException() in ICollection
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/3344147ea28ecfa9.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/CollectionReflector.cs:91
if (TryGetCollectionAdder(type, mayBeICollection: false, out addMethod))
{
return XamlCollectionKind.Collection;
}
return XamlCollectionKind.None;
}
internal static MethodInfo LookupAddMethod(Type type, XamlCollectionKind collectionKind)
{
MethodInfo result = null;
switch (collectionKind)
{
case XamlCollectionKind.Collection:
bool isCollection = TryGetCollectionAdder(type, mayBeICollection: true, out result);
if (isCollection && result is null)
{
throw new XamlSchemaException(SR.Format(SR.AmbiguousCollectionItemType, type));
}
break;
case XamlCollectionKind.Dictionary:
bool isDictionary = TryGetDictionaryAdder(type, mayBeIDictionary: true, out result);
if (isDictionary && result is null)
{
throw new XamlSchemaException(SR.Format(SR.AmbiguousDictionaryItemType, type));
}
break;
}
return result;
}
// Returns true if the type is an ICollection<T>. Additionally, if only one <T> is
// implemented, returns the Add method for that type.View on GitHub (pinned to 81131a70a4)