dotnet/reactive · error · ArgumentNullException

nameof(source)

Error message

nameof(source)

What it means

Thrown by the DoWhile(source, condition) overload when the source IAsyncObservable is null. DoWhile re-runs the source until the boolean condition fails, and the library null-checks its inputs at composition time. The message names source as the null parameter.

Solutions

  1. Pass a non-null IAsyncObservable<TSource> as the first argument
  2. Verify the expression producing the source actually returns a stream (e.g. it wasn't a failed Create call)
  3. Check argument order: source comes first, condition second
  4. Guard with a null check or fallback stream (AsyncEnumerable.Empty) before composing

Example fix

// before
IAsyncObservable<int> source = null;
var res = AsyncObservable.DoWhile(source, () => keepGoing); // throws
// after
IAsyncObservable<int> source = GetSource() ?? AsyncObservable.Empty<int>();
var res = AsyncObservable.DoWhile(source, () => keepGoing);
Defensive patterns

Strategy: validation

Validate before calling

if (source == null) throw new InvalidOperationException("DoWhile requires a non-null source");
var res = AsyncObservable.DoWhile(source, condition);

Type guard

bool IsStreamValid<TSource>(IAsyncObservable<TSource> s) => s is not null;

Try / catch

try
{
    var res = AsyncObservable.DoWhile(source, condition);
}
catch (ArgumentNullException ex) when (ex.ParamName == "source")
{
    res = AsyncObservable.DoWhile(AsyncObservable.Empty<TSource>(), condition);
}

Prevention

When it happens

Trigger: Calling AsyncObservable.DoWhile(null, condition) — usually when the source expression is the result of a method that returned null, a null conditional chain, or arguments passed in reverse order.

Common situations: Building query pipelines where an earlier factory call returned null; conditional stream selection where all branches were null; unit tests constructing operators with default values.

Related errors


AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15). Data as JSON: /api/errors/f0d08726dccbaa3c. Report an issue: GitHub.

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/DoWhile.cs:17

// 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.Disposables;
using System.Threading.Tasks;

namespace System.Reactive.Linq
{
    public partial class AsyncObservable
    {
        // REVIEW: Use a tail-recursive sink.

        public static IAsyncObservable<TSource> DoWhile<TSource>(IAsyncObservable<TSource> source, Func<bool> condition)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (condition == null)
                throw new ArgumentNullException(nameof(condition));

            return Create(
                source,
                condition,
                static async (source, condition, observer) =>
                {
                    var subscription = new SerialAsyncDisposable();

                    var o = default(IAsyncObserver<TSource>);

                    o = AsyncObserver.CreateUnsafe<TSource>(
                            observer.OnNextAsync,
                            observer.OnErrorAsync,
                            MoveNext
                        );

View on GitHub (pinned to 94b5d5ab91)