dotnet/wpf · error · InvalidOperationException

SR.InvalidOperation_IComparerFailed

Error message

SR.InvalidOperation_IComparerFailed

What it means

RBTree.Sort wraps QuickSort in a try/catch and rethrows any exception from the comparison as InvalidOperationException(SR.InvalidOperation_IComparerFailed) with the original as InnerException. It means the user-supplied comparer threw (or misbehaved) during sorting of a CollectionView.

Solutions

  1. Fix the custom IComparer so it handles nulls and mixed types and never throws
  2. Wrap Compare logic defensively and define a deterministic ordering
  3. Check the InnerException to find the faulting comparison and the objects involved

Example fix

// before
int IComparer.Compare(object x, object y) => ((Customer)x).Name.CompareTo(((Customer)y).Name); // NRE if Name null
// after
int IComparer.Compare(object x, object y) =>
    string.Compare(((Customer)x)?.Name, ((Customer)y)?.Name, StringComparison.OrdinalIgnoreCase);
Defensive patterns

Strategy: try-catch

Validate before calling

// smoke-test the comparer over the data before sorting
foreach (var (a,b) in pairs) { int r = comparer.Compare(a,b); if (comparer.Compare(b,a) != -Math.Sign(r) && r!=0) throw new InvalidOperationException("inconsistent comparer"); }

Try / catch

try { view.SortDescriptions.Add(sd); view.Refresh(); }
catch (InvalidOperationException ex) when (ex.InnerException != null) { Log.Error("IComparer threw", ex.InnerException); }

Prevention

When it happens

Trigger: CollectionView sort with a custom IComparer/SortDescription whose Compare method throws (null dereference, invalid cast, inconsistent comparisons) while RBTree.QuickSort builds the tree.

Common situations: Comparer assuming non-null values on data with nulls, comparing incompatible types after a schema/data change, comparer throwing on removed/refreshed items mid-sort.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Data/RBTree.cs:125

                node.InsertAt(finger.Offset, x, successor, succsucc);
            }

            LeftChild.IsRed = false;

#if RBTreeFlightRecorder
            Verify(size + 1, checkSort);
#endif
        }

        public void Sort()
        {
            try
            {
                QuickSort();
            }
            catch (Exception e)
            {
                throw new InvalidOperationException(SR.InvalidOperation_IComparerFailed, e);
            }
        }

        public void QuickSort()
        {
#if RBTreeFlightRecorder
            SaveTree();
            int size = Count;
#endif

            if (Count > 1)
            {
                RBFinger<T> low = FindIndex(0, false);
                RBFinger<T> high = FindIndex(Count, false);

                QuickSort3(low, high);
                InsertionSortImpl();
            }

View on GitHub (pinned to 81131a70a4)