{"record":{"id":"5e961b27de6d6a27","repo":"dotnet/reactive","slug":"until","errorCode":null,"errorMessage":"until","messagePattern":"until","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/SkipUntil.cs","lineNumber":19,"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;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace System.Reactive.Linq\n{\n    public partial class AsyncObservable\n    {\n        public static IAsyncObservable<TSource> SkipUntil<TSource, TUntil>(this IAsyncObservable<TSource> source, IAsyncObservable<TUntil> until)\n        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n            if (until == null)\n                throw new ArgumentNullException(nameof(until));\n\n            return CreateAsyncObservable<TSource>.From(\n                source,\n                until,\n                static async (source, until, observer) =>\n                {\n                    var (sourceObserver, untilObserver) = AsyncObserver.SkipUntil<TSource, TUntil>(observer);\n\n                    var sourceTask = source.SubscribeSafeAsync(sourceObserver);\n                    var untilTask = until.SubscribeSafeAsync(untilObserver);\n\n                    // REVIEW: Consider concurrent subscriptions.\n\n                    var d1 = await sourceTask.ConfigureAwait(false);\n                    var d2 = await untilTask.ConfigureAwait(false);\n\n                    return StableCompositeAsyncDisposable.Create(d1, d2);\n                });","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/SkipUntil.cs#L1-L37","documentation":"AsyncObservable.SkipUntil<TSource, TUntil> throws ArgumentNullException when the until observable is null. The until sequence controls when the gate opens and starts forwarding source emissions; without it the operator cannot function, so it is validated before CreateAsyncObservable.From is invoked.","triggerScenarios":"Calling source.SkipUntil(null), or passing a 'trigger' observable produced by a method that returned null (e.g. an event stream that is not yet wired up).","commonSituations":"Combining UI or signal streams where the trigger stream is optional and null in some flows; lazy initialization of the until observable that has not run yet; typos when wiring up multiple streams.","solutions":["Pass a valid IAsyncObservable<TUntil> as the until argument.","If the trigger is genuinely optional, use a never-completing placeholder observable instead of null.","Initialize the trigger stream before building the query."],"exampleFix":"// before\nvar result = source.SkipUntil(triggerStream); // triggerStream null when no trigger registered\n// after\nvar until = triggerStream ?? AsyncObservable.Never<int>();\nvar result = source.SkipUntil(until);","handlingStrategy":"validation","validationCode":"if (until is null) until = AsyncObservable.Never<TUntil>(); // or throw with context\nvar q = source.SkipUntil(until);","typeGuard":"static bool HasTrigger<TUntil>(IAsyncObservable<TUntil>? u) => u is not null;","tryCatchPattern":"try { var q = source.SkipUntil(until); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"until\") { /* supply default trigger */ }","preventionTips":["Replace optional trigger streams with AsyncObservable.Never<T>() instead of null.","Initialize trigger streams before building dependent queries.","Assert non-null trigger streams in tests."],"tags":["argumentnull","observable","reactive"],"backgroundTag":"null-argument","analyzedSha":"94b5d5ab912789f5abe9a72138a25bbd716fe59c","analyzedAt":"2026-09-15T02:26:24.759Z","contentChangedAt":"2026-09-15T02:26:24.759Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}