{"record":{"id":"efcd8ef80046a65a","repo":"dotnet/reactive","slug":"scheduler-takeuntil","errorCode":null,"errorMessage":"scheduler","messagePattern":"scheduler","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/TakeUntil.cs","lineNumber":65,"sourceCode":"            return CreateAsyncObservable<TSource>.From(\n                source,\n                endTime,\n                static async (source, endTime, observer) =>\n                {\n                    var (sourceObserver, timer) = await AsyncObserver.TakeUntil(observer, endTime).ConfigureAwait(false);\n\n                    var subscription = await source.SubscribeSafeAsync(sourceObserver).ConfigureAwait(false);\n\n                    return StableCompositeAsyncDisposable.Create(subscription, timer);\n                });\n        }\n\n        public static IAsyncObservable<TSource> TakeUntil<TSource>(this IAsyncObservable<TSource> source, DateTimeOffset endTime, 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            // REVIEW: May be easier to just use TakeUntil with a Timer parameter. Do we want TakeUntil on the observer?\n\n            return CreateAsyncObservable<TSource>.From(\n                source,\n                (endTime, scheduler),\n                static async (source, state, observer) =>\n                {\n                    var (sourceObserver, timer) = await AsyncObserver.TakeUntil(observer, state.endTime, state.scheduler).ConfigureAwait(false);\n\n                    var subscription = await source.SubscribeSafeAsync(sourceObserver).ConfigureAwait(false);\n\n                    return StableCompositeAsyncDisposable.Create(subscription, timer);\n                });\n        }\n    }\n\n    public partial class AsyncObserver","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/TakeUntil.cs#L47-L83","documentation":"The TakeUntil(source, endTime, scheduler) overload throws ArgumentNullException because the scheduler argument was null. The operator needs an IAsyncScheduler to schedule the end-time timer; the library rejects a null scheduler immediately with the parameter name 'scheduler' in the message. Note this overload validates both source and scheduler, so either being null yields this exception with the corresponding name.","triggerScenarios":"Calling AsyncObservable.TakeUntil(source, endTime, null) with a null IAsyncScheduler.","commonSituations":"A scheduler resolved from DI/configuration that failed to bind; passing a variable of type IAsyncScheduler that was never assigned; test code where the mock scheduler factory returned null.","solutions":["Pass an explicit scheduler such as TaskPoolAsyncScheduler.Default or a NewThreadScheduler instance.","Use the simpler TakeUntil(source, endTime) overload, which defaults to an appropriate scheduler.","If the scheduler comes from configuration, validate it is bound before building the pipeline."],"exampleFix":"// before\nvar bounded = source.TakeUntil(endTime, null);\n// after\nvar bounded = source.TakeUntil(endTime, TaskPoolAsyncScheduler.Default);","handlingStrategy":"validation","validationCode":"if (scheduler == null) scheduler = TaskPoolAsyncScheduler.Default;","typeGuard":"bool HasScheduler(IAsyncScheduler? s) => s is not null;","tryCatchPattern":"try { var bounded = source.TakeUntil(endTime, scheduler); } catch (ArgumentNullException ex) when (ex.ParamName == \"scheduler\") { var bounded = source.TakeUntil(endTime); }","preventionTips":["Default to TaskPoolAsyncScheduler.Default unless you have a specific timing/dispatch requirement.","Register the scheduler in DI with a non-null default binding.","Use the scheduler-less TakeUntil overload to let the library pick a default."],"tags":["argument-null","scheduler","takeuntil","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"}