{"record":{"id":"14fbd4b488bc3c18","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-onnext-observable","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'onNext')","messagePattern":"Value cannot be null\\. \\(Parameter 'onNext'\\)","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Linq/Observable.StandardSequenceOperators.cs","lineNumber":1380,"sourceCode":"        /// </summary>\n        /// <typeparam name=\"TSource\">The type of the elements in the source sequence.</typeparam>\n        /// <typeparam name=\"TResult\">The type of the elements in the projected inner sequences and the elements in the merged result sequence.</typeparam>\n        /// <param name=\"source\">An observable sequence of notifications to project.</param>\n        /// <param name=\"onNext\">A transform function to apply to each element.</param>\n        /// <param name=\"onError\">A transform function to apply when an error occurs in the source sequence.</param>\n        /// <param name=\"onCompleted\">A transform function to apply when the end of the source sequence is reached.</param>\n        /// <returns>An observable sequence whose elements are the result of invoking the one-to-many transform function corresponding to each notification in the input sequence.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"source\"/> or <paramref name=\"onNext\"/> or <paramref name=\"onError\"/> or <paramref name=\"onCompleted\"/> is null.</exception>\n        public static IObservable<TResult> SelectMany<TSource, TResult>(this IObservable<TSource> source, Func<TSource, IObservable<TResult>> onNext, Func<Exception, IObservable<TResult>> onError, Func<IObservable<TResult>> onCompleted)\n        {\n            if (source == null)\n            {\n                throw new ArgumentNullException(nameof(source));\n            }\n\n            if (onNext == null)\n            {\n                throw new ArgumentNullException(nameof(onNext));\n            }\n\n            if (onError == null)\n            {\n                throw new ArgumentNullException(nameof(onError));\n            }\n\n            if (onCompleted == null)\n            {\n                throw new ArgumentNullException(nameof(onCompleted));\n            }\n\n            return s_impl.SelectMany(source, onNext, onError, onCompleted);\n        }\n\n        /// <summary>\n        /// Projects each notification of an observable sequence to an observable sequence by incorporating the element's index and merges the resulting observable sequences into one observable sequence.\n        /// </summary>","sourceCodeStart":1362,"sourceCodeEnd":1398,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Linq/Observable.StandardSequenceOperators.cs#L1362-L1398","documentation":"Thrown by the notification-based SelectMany(source, onNext, onError, onCompleted) overload when the onNext delegate (Func<TSource, IObservable<TResult>>) is null. Rx requires all three notification handlers because each notification kind must map to a sequence; a null onNext is rejected eagerly at call time.","triggerScenarios":"Calling Observable.SelectMany(source, null, onError, onCompleted) — the element-to-observable projection is null, commonly when the onError/onCompleted handlers are supplied but the element handler was omitted by mistake.","commonSituations":"Confusion with Subscribe-style handlers where passing null for onNext is legal; copying the Subscribe(source, null, onError, onCompleted) pattern into SelectMany; conditional construction where only error handling was implemented so far.","solutions":["Provide an onNext lambda projecting each element to an IObservable<TResult>, e.g. x => Observable.Return(Process(x)).","If elements should be ignored, pass x => Observable.Empty<TResult>() instead of null.","Use a different SelectMany overload (single selector) if no per-notification handling is required."],"exampleFix":"// before\nvar q = source.SelectMany(null, err => Observable.Throw<Item>(err), () => Observable.Empty<Item>());\n\n// after\nvar q = source.SelectMany(x => Observable.Return(Process(x)), err => Observable.Throw<Item>(err), () => Observable.Empty<Item>());","handlingStrategy":"validation","validationCode":"if (onNext is null) throw new ArgumentNullException(nameof(onNext)); // check before invoking SelectMany","typeGuard":"static bool HandlersValid<TSource, TResult>(Func<TSource, IObservable<TResult>> onNext)\n    => onNext is not null;","tryCatchPattern":"try\n{\n    var q = source.SelectMany(onNext, onError, onCompleted);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"onNext\")\n{\n    // substitute a default element mapping\n    q = source.SelectMany(x => Observable.Empty<TResult>(), onError, onCompleted);\n}","preventionTips":["Do not carry the Subscribe convention (null handlers allowed) into Rx LINQ operators.","For 'ignore elements' semantics pass x => Observable.Empty<TResult>() instead of null.","Keep the three notification handlers grouped in a small helper so they are always supplied together."],"tags":["null-argument","argument-validation","reactive-extensions","linq"],"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"}