dotnet/reactive · error · ArgumentNullException
until
Error message
until
What it means
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.
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.
Example fix
// before var result = source.SkipUntil(triggerStream); // triggerStream null when no trigger registered // after var until = triggerStream ?? AsyncObservable.Never<int>(); var result = source.SkipUntil(until);
Defensive patterns
Strategy: validation
Validate before calling
if (until is null) until = AsyncObservable.Never<TUntil>(); // or throw with context var q = source.SkipUntil(until);
Type guard
static bool HasTrigger<TUntil>(IAsyncObservable<TUntil>? u) => u is not null;
Try / catch
try { var q = source.SkipUntil(until); }
catch (ArgumentNullException ex) when (ex.ParamName == "until") { /* supply default trigger */ } Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/5e961b27de6d6a27.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/SkipUntil.cs:19
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT License.
// See the LICENSE file in the project root for more information.
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
using System.Threading;
using System.Threading.Tasks;
namespace System.Reactive.Linq
{
public partial class AsyncObservable
{
public static IAsyncObservable<TSource> SkipUntil<TSource, TUntil>(this IAsyncObservable<TSource> source, IAsyncObservable<TUntil> until)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (until == null)
throw new ArgumentNullException(nameof(until));
return CreateAsyncObservable<TSource>.From(
source,
until,
static async (source, until, observer) =>
{
var (sourceObserver, untilObserver) = AsyncObserver.SkipUntil<TSource, TUntil>(observer);
var sourceTask = source.SubscribeSafeAsync(sourceObserver);
var untilTask = until.SubscribeSafeAsync(untilObserver);
// REVIEW: Consider concurrent subscriptions.
var d1 = await sourceTask.ConfigureAwait(false);
var d2 = await untilTask.ConfigureAwait(false);
return StableCompositeAsyncDisposable.Create(d1, d2);
});View on GitHub (pinned to 94b5d5ab91)