{"record":{"id":"6d6f3cafb1a118b9","repo":"dotnet/reactive","slug":"scheduler-subscribeon","errorCode":null,"errorMessage":"scheduler","messagePattern":"scheduler","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/SubscribeOn.cs","lineNumber":17,"sourceCode":"﻿// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under the MIT License.\n// See the LICENSE file in the project root for more information. \n\nusing System.Reactive.Concurrency;\nusing System.Reactive.Disposables;\n\nnamespace System.Reactive.Linq\n{\n    public partial class AsyncObservable\n    {\n        public static IAsyncObservable<TSource> SubscribeOn<TSource>(this IAsyncObservable<TSource> source, IAsyncScheduler scheduler)\n        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n            if (scheduler == null)\n                throw new ArgumentNullException(nameof(scheduler));\n\n            return SubscribeOn(source, scheduler, scheduler);\n        }\n\n        public static IAsyncObservable<TSource> SubscribeOn<TSource>(this IAsyncObservable<TSource> source, IAsyncScheduler subscribeScheduler, IAsyncScheduler disposeScheduler)\n        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n            if (subscribeScheduler == null)\n                throw new ArgumentNullException(nameof(subscribeScheduler));\n            if (disposeScheduler == null)\n                throw new ArgumentNullException(nameof(disposeScheduler));\n\n            return CreateAsyncObservable<TSource>.From(\n                source,\n                (subscribeScheduler, disposeScheduler),\n                static async (source, state, observer) =>\n                {","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/SubscribeOn.cs#L1-L35","documentation":"SubscribeOn(source, scheduler) validates the scheduler after the source. Passing a null scheduler throws ArgumentNullException(\"scheduler\") since the operator cannot schedule subscription/disposition work without one.","triggerScenarios":"Calling source.SubscribeOn(null), or SubscribeOn(source, scheduler) where scheduler comes from an uninitialized field, failed DI resolution, or wrong positional argument.","commonSituations":"Scheduler injected via configuration not registered in DI; a custom scheduler factory returns null; argument-order swap when upgrading from a two- to three-parameter overload.","solutions":["Pass a valid IAsyncScheduler instance, e.g. AsyncScheduler.DefaultScheduler.","Fix the null source of the scheduler (DI registration, config).","Verify you're not confusing the (source, scheduler) and (source, subscribeScheduler, disposeScheduler) overloads."],"exampleFix":"// before\nvar obs = source.SubscribeOn(uiScheduler); // uiScheduler is null\n// after\nvar obs = source.SubscribeOn(uiScheduler ?? AsyncScheduler.DefaultScheduler);","handlingStrategy":"validation","validationCode":"if (scheduler == null)\n    scheduler = AsyncScheduler.DefaultScheduler; // safe fallback before the call","typeGuard":"bool HasScheduler(IAsyncScheduler? s) => s is not null;","tryCatchPattern":"try\n{\n    var obs = source.SubscribeOn(scheduler);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"scheduler\")\n{\n    logger.LogError(ex, \"Null scheduler passed to SubscribeOn\");\n    obs = source.SubscribeOn(AsyncScheduler.DefaultScheduler);\n}","preventionTips":["Centralize scheduler resolution in one helper that never returns null.","Register schedulers in DI eagerly and assert resolution at startup.","Prefer the single-scheduler overload unless you truly need split subscribe/dispose scheduling."],"tags":["argument-null","scheduler","async-rx"],"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"}