{"record":{"id":"e31671a5be84617d","repo":"dotnet/reactive","slug":"selector-observableex","errorCode":null,"errorMessage":"selector","messagePattern":"selector","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Linq/ObservableEx.cs","lineNumber":82,"sourceCode":"        /// Expands an observable sequence by recursively invoking selector, using the specified scheduler to enumerate the queue of obtained sequences.\n        /// </summary>\n        /// <typeparam name=\"TSource\">The type of the elements in the source sequence and each of the recursively expanded sources obtained by running the selector function.</typeparam>\n        /// <param name=\"source\">Source sequence with the initial elements.</param>\n        /// <param name=\"selector\">Selector function to invoke for each produced element, resulting in another sequence to which the selector will be invoked recursively again.</param>\n        /// <param name=\"scheduler\">Scheduler on which to perform the expansion by enumerating the internal queue of obtained sequences.</param>\n        /// <returns>An observable sequence containing all the elements produced by the recursive expansion.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"source\"/> or <paramref name=\"selector\"/> or <paramref name=\"scheduler\"/> is null.</exception>\n        [Experimental]\n        public static IObservable<TSource> Expand<TSource>(this IObservable<TSource> source, Func<TSource, IObservable<TSource>> selector, IScheduler scheduler)\n        {\n            if (source == null)\n            {\n                throw new ArgumentNullException(nameof(source));\n            }\n\n            if (selector == null)\n            {\n                throw new ArgumentNullException(nameof(selector));\n            }\n\n            if (scheduler == null)\n            {\n                throw new ArgumentNullException(nameof(scheduler));\n            }\n\n            return s_impl.Expand(source, selector, scheduler);\n        }\n\n        /// <summary>\n        /// Expands an observable sequence by recursively invoking selector.\n        /// </summary>\n        /// <typeparam name=\"TSource\">The type of the elements in the source sequence and each of the recursively expanded sources obtained by running the selector function.</typeparam>\n        /// <param name=\"source\">Source sequence with the initial elements.</param>\n        /// <param name=\"selector\">Selector function to invoke for each produced element, resulting in another sequence to which the selector will be invoked recursively again.</param>\n        /// <returns>An observable sequence containing all the elements produced by the recursive expansion.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"source\"/> or <paramref name=\"selector\"/> is null.</exception>","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Linq/ObservableEx.cs#L64-L100","documentation":"Expand(source, selector, scheduler) requires a non-null selector Func<TSource, IObservable<TSource>> that recursively expands each element. A null selector throws ArgumentNullException synchronously at the call site. The selector is the core of the operator; without it no expansion can be defined.","triggerScenarios":"Passing a null selector lambda — commonly an optional strategy delegate that was never assigned, or a method group built via reflection that returned null.","commonSituations":"Pluggable expansion strategies in tests left null, config-selected delegates that fail to resolve, refactoring that removed the selector body but kept the null variable.","solutions":["Provide a valid selector before calling Expand","If expansion is optional, use the source directly (or Observable.Empty chains) instead of a null selector","Validate DI/config-provided delegates for null at composition time"],"exampleFix":"// before\nvar expanded = source.Expand(expansionStrategy, Scheduler.Default); // strategy null\n// after\nvar expanded = source.Expand(expansionStrategy ?? (x => Observable.Empty<Node>()), Scheduler.Default);","handlingStrategy":"validation","validationCode":"if (selector == null) throw new ArgumentNullException(nameof(selector), \"Expand requires a non-null selector.\");","typeGuard":"bool IsValidSelector<TSource>(Func<TSource, IObservable<TSource>> f) => f is not null;","tryCatchPattern":"try { var expanded = source.Expand(selector, scheduler); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"selector\") { log.Error(\"Expand selector was null\", ex); }","preventionTips":["Provide a default expansion strategy (e.g. return Empty) for optional behavior","Verify reflection/config-resolved delegates before use","Keep selector lambdas inline when they are not meant to be optional"],"tags":["csharp","null-argument","experimental-api","reactive-extensions"],"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"}