{"record":{"id":"8b9ffd61d40431e3","repo":"louthy/language-ext","slug":"invalidoperationexception-ordresolver","errorCode":null,"errorMessage":"InvalidOperationException","messagePattern":"InvalidOperationException","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"LanguageExt.Core/Traits/Resolve/OrdResolver.cs","lineNumber":77,"sourceCode":"        {\n            ResolutionError = $\"Trait implementation not found for: {source.Name}\";\n            MakeDefault();\n            return;\n        }\n        \n        // Compare\n        \n        var m = Resolver.Method(impl, \"Compare\", source, source);\n        if (m is null)\n        {\n            ResolutionError = $\"`Compare` method not found for: {source.Name}\";\n            MakeDefault();\n            return;\n        }\n\n        CompareMethod    = m;\n        CompareMethodPtr = m.MethodHandle.GetFunctionPointer();\n        CompareFunc      = (x, y) => (int?)CompareMethod.Invoke(null, [x, y]) ?? throw new InvalidOperationException();\n\n        // Equals\n        \n        m = Resolver.Method(impl, \"Equals\", source, source);\n        if (m is null)\n        {\n            ResolutionError = $\"`Equals` method not found for: {source.Name}\";\n            MakeDefault();\n            return;\n        }\n\n        EqualsMethod    = m;\n        EqualsMethodPtr = m.MethodHandle.GetFunctionPointer();\n        EqualsFunc      = (x, y) => (bool?)EqualsMethod.Invoke(null, [x, y]) ?? throw new InvalidOperationException();\n        \n        // GetHashCode\n        \n        m = Resolver.Method(impl, \"GetHashCode\", source);","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/louthy/language-ext/blob/2f0e3628242889774d4141960a35671a0280051f/LanguageExt.Core/Traits/Resolve/OrdResolver.cs#L59-L95","documentation":"OrdResolver.MakeComparer resolves the Ord<A> implementation's Compare method via reflection and wraps it in CompareFunc. That delegate throws InvalidOperationException if the Invoke result is null where an int was required, meaning the resolved Compare member doesn't conform to static int Compare(A,A).","triggerScenarios":"Using Ord<A>-based ordering (sort, min/max, comparison APIs) on a type whose Ord implementation's Compare(A,A) returns null (wrong return type or null-producing body) when the delegate is invoked.","commonSituations":"Hand-rolled Ord instances with nullable int returns; refactors that changed Compare's signature; reflection-based resolution picking a wrong overload; trimming removing the real method.","solutions":["Fix Compare to be static, take (A, A), and return a non-null int.","Remove the broken Ord implementation so OrdResolver.MakeDefault (Comparer<A>.Default) applies.","Add a unit test that exercises comparison through the trait before shipping.","Audit all static members named 'Compare' on the type for accidental overload collisions."],"exampleFix":"// before\npublic static int? Compare(A x, A y) => null;\n// after\npublic static int Compare(A x, A y) => Comparer<A>.Default.Compare(x, y);","handlingStrategy":"validation","validationCode":"var m = typeof(OrdImpl).GetMethod(\"Compare\", new[] { typeof(A), typeof(A) });\nbool ok = m is { IsStatic: true } && m.ReturnType == typeof(int);","typeGuard":"bool IsValidCompare<A>(MethodInfo? m) => m is { IsStatic: true } && m.ReturnType == typeof(int) && m.GetParameters().Length == 2;","tryCatchPattern":"try { ordered = items.OrderBy(x => x, Ord<A>.Default); }\ncatch (InvalidOperationException) { ordered = items.OrderBy(x => x, Comparer<A>.Default); }","preventionTips":["Static int Compare(A, A) — no nullable returns","Smoke-test sorting a sample collection early in development","Avoid overloads named Compare with different shapes on the same type","Fallback to Comparer<A>.Default in infrastructure code"],"tags":["reflection","ordering","resolver","languageext"],"backgroundTag":"invalid-argument-value","analyzedSha":"2f0e3628242889774d4141960a35671a0280051f","analyzedAt":"2026-09-15T03:31:55.716Z","contentChangedAt":"2026-09-15T03:31:55.716Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}