stride3d/stride · error · InvalidOperationException
No comparison available or provided for items of this…
Error message
No comparison available or provided for items of this collection.
What it means
GetIndex locates (or computes the insert index for) an item via DefaultCompareFunc. If no comparison function is available (null) when GetIndex is invoked — e.g. the collection was created through a path that skipped comparer resolution — it throws InvalidOperationException instead of silently mis-ordering.
Solutions
- Recreate the collection with a valid comparer or ensure T implements IComparable
- Pass a comparison function through the constructor overload used by your subclass
- Check the initialization path (e.g. deserialization) that produced a comparer-less collection
- Call the GetIndex overload that takes an explicit compareFunc when no default is available
Example fix
// before var idx = col.GetIndex(item, false); // DefaultCompareFunc null // after var col = new SortedObservableCollection<MyVm>(Comparer<MyVm>.Create((a, b) => a.Name.CompareTo(b.Name))); var idx = col.GetIndex(item, false);
Defensive patterns
Strategy: validation
Validate before calling
var safeCol = col.DefaultCompareFunc != null ? col : new SortedObservableCollection<T>(Comparer<T>.Create(cmp));
Try / catch
try { var idx = col.GetIndex(item, false); } catch (InvalidOperationException) { /* comparer missing; rebuild collection with comparer */ } Prevention
- Construct SortedObservableCollection only through constructors that resolve a comparer
- Rebuild with a comparer after deserialization
- Pass an explicit compareFunc when invoking index-search helpers on subclasses
When it happens
Trigger: Calling methods that rely on GetIndex (insert, binary search, index lookup) on a SortedObservableCollection whose DefaultCompareFunc is null — typically via a constructor path that did not resolve a comparer, or after the comparer was cleared.
Common situations: Subclasses that bypass the validating constructor; deserialization rebuilding the collection without a comparer; calling protected sorting helpers on a badly initialized instance.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- The type of this collection does not implement any…
- A PackageViewModel cannot contain two isntances of…
- An element with the same key has already been added.
- An id is both marked as deleted and associated to a key of…
- An item has been added to a collection that does not have a…
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/13be450e93ce85ad.
Report an issue: GitHub.
Appendix: source
Thrown at sources/presentation/Stride.Core.Presentation/Collections/SortedObservableCollection.cs:126
{
if (typeof(T).GetInterfaces().Contains(typeof(IComparable<TSearch>)))
compareFunc = (item1, item2) => ((IComparable<TSearch>)item1!).CompareTo(item2);
else
throw new ArgumentNullException(nameof(compareFunc));
}
return GetIndex(key, false, compareFunc);
}
/// <inheritdoc/>
public override string ToString()
{
return $"{{SortedObservableCollection}} Count = {Count}";
}
protected int GetIndex(T item, bool returnInsertIndex)
{
if (DefaultCompareFunc is null) throw new InvalidOperationException("No comparison available or provided for items of this collection.");
return GetIndex(item, returnInsertIndex, DefaultCompareFunc.Invoke);
}
protected int GetIndex<TSearch>(TSearch key, bool returnInsertIndex, Func<T, TSearch, int> compareFunc)
{
int imin = 0;
int imax = Count - 1;
while (imax >= imin)
{
int imid = (imin + imax) / 2;
int comp = compareFunc(this[imid], key);
if (comp < 0)
imin = imid + 1;
else if (comp > 0)
imax = imid - 1;
else
return imid;View on GitHub (pinned to 96fad776d2)