{"record":{"id":"89722758df07d9ea","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-source-synchronization","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'source')","messagePattern":"Value cannot be null\\. \\(Parameter 'source'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Concurrency/Synchronization.cs","lineNumber":35,"sourceCode":"        #region SubscribeOn\n\n        /// <summary>\n        /// Wraps the source sequence in order to run its subscription and unsubscription logic on the specified scheduler.\n        /// </summary>\n        /// <typeparam name=\"TSource\">The type of the elements in the source sequence.</typeparam>\n        /// <param name=\"source\">Source sequence.</param>\n        /// <param name=\"scheduler\">Scheduler to perform subscription and unsubscription actions on.</param>\n        /// <returns>The source sequence whose subscriptions and unsubscriptions happen on the specified scheduler.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"source\"/> or <paramref name=\"scheduler\"/> is <c>null</c>.</exception>\n        /// <remarks>\n        /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the specified scheduler.\n        /// In order to invoke observer callbacks on the specified scheduler, e.g. to offload callback processing to a dedicated thread, use <see cref=\"Synchronization.ObserveOn{TSource}(IObservable{TSource}, IScheduler)\"/>.\n        /// </remarks>\n        public static IObservable<TSource> SubscribeOn<TSource>(IObservable<TSource> source, IScheduler scheduler)\n        {\n            if (source == null)\n            {\n                throw new ArgumentNullException(nameof(source));\n            }\n\n            if (scheduler == null)\n            {\n                throw new ArgumentNullException(nameof(scheduler));\n            }\n\n            return new SubscribeOnObservable<TSource>(source, scheduler);\n        }\n\n        private sealed class SubscribeOnObservable<TSource> : ObservableBase<TSource>\n        {\n            private sealed class Subscription : IDisposable\n            {\n                private SerialDisposableValue _cancel;\n\n                public Subscription(IObservable<TSource> source, IScheduler scheduler, IObserver<TSource> observer)\n                {","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Concurrency/Synchronization.cs#L17-L53","documentation":"ArgumentNullException thrown by Synchronization.SubscribeOn<TSource>(IObservable<TSource>, IScheduler) when the source sequence is null. SubscribeOn wraps the source in a SubscribeOnObservable so the Subscribe call itself runs on the given scheduler; the source must exist for that wrapper to delegate to.","triggerScenarios":"Calling source.SubscribeOn(scheduler) where the source expression evaluates to null — commonly a nullable field or property holding the observable, or a method that returned null instead of an empty or never sequence.","commonSituations":"Chaining off a repository or service method whose observable result is null on error paths; DI-resolved observables that failed to bind; legacy code returning null instead of Observable.Empty or Observable.Never.","solutions":["Ensure the IObservable<TSource> passed to SubscribeOn is non-null; replace null-returning producers with Observable.Empty<TSource>() or Observable.Never<TSource>().","Null-check the source before calling SubscribeOn and handle the null case (log, throw a domain error, or use a fallback sequence).","Fix the upstream factory or DI registration so the observable is always produced instead of returning null.","Guard at the call site so a null source fails fast with your own descriptive exception if that is the intended contract."],"exampleFix":"// before\nIObservable<int> source = _repository.GetData(); // may return null\nvar scheduled = source.SubscribeOn(Scheduler.ThreadPool);\n// after\nIObservable<int> source = _repository.GetData() ?? Observable.Empty<int>();\nvar scheduled = source.SubscribeOn(Scheduler.ThreadPool);","handlingStrategy":"validation","validationCode":"if (source == null) throw new InvalidOperationException(\"Source observable must not be null before SubscribeOn\");\nvar scheduled = source.SubscribeOn(Scheduler.ThreadPool);","typeGuard":"bool IsUsableSource<TSource>(IObservable<TSource> source) => source is not null;","tryCatchPattern":"try\n{\n    var scheduled = source.SubscribeOn(Scheduler.ThreadPool);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"source\")\n{\n    scheduled = Observable.Empty<TSource>().SubscribeOn(Scheduler.ThreadPool);\n}","preventionTips":["Return Observable.Empty or Observable.Never from producers instead of null.","Null-check observables returned from services before composing pipelines.","Ensure DI registrations for observable dependencies exist before pipelines are built.","Prefer Observable.Defer for lazily-created sources so construction errors surface at subscription time."],"tags":["csharp","dotnet","null-argument","rx","scheduler"],"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"}