{"record":{"id":"cd9e284d854e1ebd","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-comparer-sequenceequal","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'comparer')","messagePattern":"Value cannot be null\\. \\(Parameter 'comparer'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/SequenceEqual.cs","lineNumber":48,"sourceCode":"                    var secondTask = second.SubscribeSafeAsync(secondObserver);\n\n                    // REVIEW: Consider concurrent subscriptions.\n\n                    var d1 = await firstTask.ConfigureAwait(false);\n                    var d2 = await secondTask.ConfigureAwait(false);\n\n                    return StableCompositeAsyncDisposable.Create(d1, d2);\n                });\n        }\n\n        public static IAsyncObservable<bool> SequenceEqual<TSource>(this IAsyncObservable<TSource> first, IAsyncObservable<TSource> second, IEqualityComparer<TSource> comparer)\n        {\n            if (first == null)\n                throw new ArgumentNullException(nameof(first));\n            if (second == null)\n                throw new ArgumentNullException(nameof(second));\n            if (comparer == null)\n                throw new ArgumentNullException(nameof(comparer));\n\n            return CreateAsyncObservable<bool>.From(\n                first,\n                (second, comparer),\n                static async (first, state, observer) =>\n                {\n                    var (firstObserver, secondObserver) = AsyncObserver.SequenceEqual(observer, state.comparer);\n\n                    var firstTask = first.SubscribeSafeAsync(firstObserver);\n                    var secondTask = state.second.SubscribeSafeAsync(secondObserver);\n\n                    // REVIEW: Consider concurrent subscriptions.\n\n                    var d1 = await firstTask.ConfigureAwait(false);\n                    var d2 = await secondTask.ConfigureAwait(false);\n\n                    return StableCompositeAsyncDisposable.Create(d1, d2);\n                });","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/SequenceEqual.cs#L30-L66","documentation":"The comparer-based SequenceEqual overload requires a non-null IEqualityComparer<TSource>; a null comparer throws ArgumentNullException with parameter 'comparer'. Unlike LINQ-to-Objects, this library does not default a null comparer to EqualityComparer<T>.Default.","triggerScenarios":"Calling first.SequenceEqual(second, null) where the comparer comes from an optional parameter, DI-resolved service, or config-driven selection that yielded null.","commonSituations":"Optional comparer parameters defaulted to null instead of EqualityComparer<TSource>.Default; dependency-injected comparer not registered; settings key missing so the comparer factory returns null.","solutions":["Pass an explicit comparer, e.g. EqualityComparer<TSource>.Default or Comparer-based lambda wrapper.","Coalesce the comparer: comparer ?? EqualityComparer<TSource>.Default.","Fix the DI registration or factory so the comparer is always provided.","If the comparer is truly optional, call the two-argument SequenceEqual overload instead."],"exampleFix":"// before\nvar eq = left.SequenceEqual(right, options.Comparer); // options.Comparer is null\n// after\nvar eq = left.SequenceEqual(right, options.Comparer ?? EqualityComparer<string>.Default);","handlingStrategy":"validation","validationCode":"comparer ??= EqualityComparer<TSource>.Default;","typeGuard":"static bool HasComparer<T>(IEqualityComparer<T>? c) => c is not null;","tryCatchPattern":"try { var eq = left.SequenceEqual(right, comparer); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"comparer\") { var eq2 = left.SequenceEqual(right); /* default comparer */ }","preventionTips":["Default optional comparer parameters to EqualityComparer<T>.Default, never null.","Verify DI registrations for comparer services at startup.","Prefer the two-argument overload when no custom comparer is needed."],"tags":["argument-null","sequenceequal","comparer","asyncrx"],"backgroundTag":"null-argument","analyzedSha":"94b5d5ab912789f5abe9a72138a25bbd716fe59c","analyzedAt":"2026-09-15T02:26:24.759Z","contentChangedAt":"2026-09-15T02:26:24.759Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}