{"record":{"id":"fbf800f9e0b8dbca","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-resultselector-observable","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'resultSelector')","messagePattern":"Value cannot be null\\. \\(Parameter 'resultSelector'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Linq/Observable.Aggregates.cs","lineNumber":69,"sourceCode":"        /// <param name=\"resultSelector\">A function to transform the final accumulator value into the result value.</param>\n        /// <returns>An observable sequence containing a single element with the final accumulator value.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"source\"/> or <paramref name=\"accumulator\"/> or <paramref name=\"resultSelector\"/> is null.</exception>\n        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>\n        public static IObservable<TResult> Aggregate<TSource, TAccumulate, TResult>(this IObservable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, Func<TAccumulate, TResult> resultSelector)\n        {\n            if (source == null)\n            {\n                throw new ArgumentNullException(nameof(source));\n            }\n\n            if (accumulator == null)\n            {\n                throw new ArgumentNullException(nameof(accumulator));\n            }\n\n            if (resultSelector == null)\n            {\n                throw new ArgumentNullException(nameof(resultSelector));\n            }\n\n            return s_impl.Aggregate(source, seed, accumulator, resultSelector);\n        }\n\n        /// <summary>\n        /// Applies an accumulator function over an observable sequence, returning the result of the aggregation as a single element in the result sequence.\n        /// For aggregation behavior with incremental intermediate results, see <see cref=\"Observable.Scan{TSource}\"/>.\n        /// </summary>\n        /// <typeparam name=\"TSource\">The type of the elements in the source sequence and the result of the aggregation.</typeparam>\n        /// <param name=\"source\">An observable sequence to aggregate over.</param>\n        /// <param name=\"accumulator\">An accumulator function to be invoked on each element.</param>\n        /// <returns>An observable sequence containing a single element with the final accumulator value.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"source\"/> or <paramref name=\"accumulator\"/> is null.</exception>\n        /// <exception cref=\"InvalidOperationException\">(Asynchronous) The source sequence is empty.</exception>\n        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>\n        public static IObservable<TSource> Aggregate<TSource>(this IObservable<TSource> source, Func<TSource, TSource, TSource> accumulator)\n        {","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Linq/Observable.Aggregates.cs#L51-L87","documentation":"The full Aggregate overload throws ArgumentNullException when resultSelector is null. The resultSelector converts the final accumulated value into the output type; without it the operator cannot produce a result, so validation fails synchronously before any subscription occurs.","triggerScenarios":"Calling Observable.Aggregate(source, seed, accumulator, null) — e.g. omitting the projection because the accumulator already seemed sufficient, or passing a null conditional projection delegate.","commonSituations":"Refactors that replaced the selector with direct use of the accumulate type but left the 4-arg call; frameworks injecting an optional mapper that defaults to null; generic helpers where the selector parameter was never bound.","solutions":["Pass an identity selector, x => x, when no projection is needed.","Switch to the 3-parameter overload (source, seed, accumulator) if no result projection is required.","Default the selector to Func<TAccumulate, TResult> identity when resolved dynamically.","Enable nullable reference types to catch the null selector at compile time."],"exampleFix":"// before\nawait src.Aggregate(0, (a, x) => a + x, null); // ArgumentNullException\n\n// after\nawait src.Aggregate(0, (a, x) => a + x, x => x); // or use the 3-arg overload","handlingStrategy":"type-guard","validationCode":"if (resultSelector is null) resultSelector = x => x; // identity fallback","typeGuard":"static Func<T, TResult> NotNull<T, TResult>(Func<T, TResult>? f) => f ?? (x => x!);","tryCatchPattern":"try { var result = source.Aggregate(seed, acc, selector); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"resultSelector\") { /* use identity selector or 3-arg overload */ }","preventionTips":["Use the 3-parameter Aggregate overload when no projection is needed.","Pass x => x explicitly instead of null to signal identity projection.","Default optional selectors to identity functions in wrapper APIs.","Enable nullable reference types to catch null selectors statically."],"tags":["rx","argument-null","aggregate-operator","delegate-null"],"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"}