{"record":{"id":"3d975f2b3395b2f3","repo":"dotnet/reactive","slug":"argumentnullexception-default-message-value-cannot-be-null-3d975f","errorCode":null,"errorMessage":"ArgumentNullException (default message: Value cannot be null. (Parameter 'keySelector'))","messagePattern":"ArgumentNullException \\(default message: Value cannot be null\\. \\(Parameter 'keySelector'\\)\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Linq/Observable.StandardSequenceOperators.cs","lineNumber":138,"sourceCode":"        /// Returns an observable sequence that contains only distinct elements according to the keySelector.\n        /// </summary>\n        /// <typeparam name=\"TSource\">The type of the elements in the source sequence.</typeparam>\n        /// <typeparam name=\"TKey\">The type of the discriminator key computed for each element in the source sequence.</typeparam>\n        /// <param name=\"source\">An observable sequence to retain distinct elements for.</param>\n        /// <param name=\"keySelector\">A function to compute the comparison key for each element.</param>\n        /// <returns>An observable sequence only containing the distinct elements, based on a computed key value, from the source sequence.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"source\"/> or <paramref name=\"keySelector\"/> is null.</exception>\n        /// <remarks>Usage of this operator should be considered carefully due to the maintenance of an internal lookup structure which can grow large.</remarks>\n        public static IObservable<TSource> Distinct<TSource, TKey>(this IObservable<TSource> source, Func<TSource, TKey> keySelector)\n        {\n            if (source == null)\n            {\n                throw new ArgumentNullException(nameof(source));\n            }\n\n            if (keySelector == null)\n            {\n                throw new ArgumentNullException(nameof(keySelector));\n            }\n\n            return s_impl.Distinct(source, keySelector);\n        }\n\n        /// <summary>\n        /// Returns an observable sequence that contains only distinct elements according to the keySelector and the comparer.\n        /// </summary>\n        /// <typeparam name=\"TSource\">The type of the elements in the source sequence.</typeparam>\n        /// <typeparam name=\"TKey\">The type of the discriminator key computed for each element in the source sequence.</typeparam>\n        /// <param name=\"source\">An observable sequence to retain distinct elements for.</param>\n        /// <param name=\"keySelector\">A function to compute the comparison key for each element.</param>\n        /// <param name=\"comparer\">Equality comparer for source elements.</param>\n        /// <returns>An observable sequence only containing the distinct elements, based on a computed key value, from the source sequence.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"source\"/> or <paramref name=\"keySelector\"/> or <paramref name=\"comparer\"/> is null.</exception>\n        /// <remarks>Usage of this operator should be considered carefully due to the maintenance of an internal lookup structure which can grow large.</remarks>\n        public static IObservable<TSource> Distinct<TSource, TKey>(this IObservable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)\n        {","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Linq/Observable.StandardSequenceOperators.cs#L120-L156","documentation":"The Distinct(source, keySelector) overload requires a non-null keySelector because Distinct uses it to extract deduplication keys for its internal set; a null keySelector throws ArgumentNullException with Parameter 'keySelector' after source validation passes.","triggerScenarios":"Calling Distinct<TSource, TKey>(source, null) — valid source, null Func<TSource, TKey>.","commonSituations":"Storing the key selector in a variable that was never assigned, or receiving it as a null method parameter and forwarding it unchecked.","solutions":["Provide the key selector lambda directly, e.g., x => x.Id","If you truly need no projection, use the comparer-less Distinct() overload instead of a null selector","Null-check the selector where it is produced before forwarding","Fix configuration/DI that should supply the selector"],"exampleFix":"// before\nFunc<Item, int> sel = _selector; // may be null\nvar result = source.Distinct(sel);\n// after\nvar result = source.Distinct(x => x.Id);","handlingStrategy":"validation","validationCode":"if (keySelector is null) throw new ArgumentNullException(nameof(keySelector));\n// or: keySelector ??= x => x.DefaultKey;","typeGuard":"bool HasSelector<TSource,TKey>(Func<TSource,TKey>? sel) => sel is not null;","tryCatchPattern":"try { var result = source.Distinct(keySelector); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"keySelector\")\n{\n    result = source.Distinct(); // default equality without projection\n}","preventionTips":["Never forward keySelector parameters received as null — validate at the boundary","Initialize Func fields at declaration or make them required constructor dependencies","Use a default projection instead of null when the selector is configurable","Check ex.ParamName to distinguish keySelector from source validation failures"],"tags":["csharp","rx","argument-validation","null","keyselector"],"backgroundTag":"null-argument","analyzedSha":"94b5d5ab912789f5abe9a72138a25bbd716fe59c","analyzedAt":"2026-09-15T02:26:24.759Z","contentChangedAt":"2026-09-15T02:26:24.759Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}