{"record":{"id":"73cc39b08d11b625","repo":"dotnet/wpf","slug":"sr-invalidoperation-icomparerfailed","errorCode":null,"errorMessage":"SR.InvalidOperation_IComparerFailed","messagePattern":"SR\\.InvalidOperation_IComparerFailed","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Data/RBTree.cs","lineNumber":125,"sourceCode":"                node.InsertAt(finger.Offset, x, successor, succsucc);\n            }\n\n            LeftChild.IsRed = false;\n\n#if RBTreeFlightRecorder\n            Verify(size + 1, checkSort);\n#endif\n        }\n\n        public void Sort()\n        {\n            try\n            {\n                QuickSort();\n            }\n            catch (Exception e)\n            {\n                throw new InvalidOperationException(SR.InvalidOperation_IComparerFailed, e);\n            }\n        }\n\n        public void QuickSort()\n        {\n#if RBTreeFlightRecorder\n            SaveTree();\n            int size = Count;\n#endif\n\n            if (Count > 1)\n            {\n                RBFinger<T> low = FindIndex(0, false);\n                RBFinger<T> high = FindIndex(Count, false);\n\n                QuickSort3(low, high);\n                InsertionSortImpl();\n            }","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Data/RBTree.cs#L107-L143","documentation":"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.","triggerScenarios":"CollectionView sort with a custom IComparer/SortDescription whose Compare method throws (null dereference, invalid cast, inconsistent comparisons) while RBTree.QuickSort builds the tree.","commonSituations":"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.","solutions":["Fix the custom IComparer so it handles nulls and mixed types and never throws","Wrap Compare logic defensively and define a deterministic ordering","Check the InnerException to find the faulting comparison and the objects involved"],"exampleFix":"// before\nint IComparer.Compare(object x, object y) => ((Customer)x).Name.CompareTo(((Customer)y).Name); // NRE if Name null\n// after\nint IComparer.Compare(object x, object y) =>\n    string.Compare(((Customer)x)?.Name, ((Customer)y)?.Name, StringComparison.OrdinalIgnoreCase);","handlingStrategy":"try-catch","validationCode":"// smoke-test the comparer over the data before sorting\nforeach (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\"); }","typeGuard":null,"tryCatchPattern":"try { view.SortDescriptions.Add(sd); view.Refresh(); }\ncatch (InvalidOperationException ex) when (ex.InnerException != null) { Log.Error(\"IComparer threw\", ex.InnerException); }","preventionTips":["Make comparers null-safe and total (antisymmetric, transitive)","Never compare heterogeneous runtypes without checks","Test comparers against production-like data including nulls"],"tags":["wpf","collectionview","icomparer","sorting"],"backgroundTag":"invalid-argument-value","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}