dotnet/reactive · error · ArgumentNullException

new ArgumentNullException(nameof(condition))

Error message

new ArgumentNullException(nameof(condition))

What it means

The explicit-scheduler Generate overload validates condition (Func<TState, ValueTask<bool>>) second and throws ArgumentNullException(nameof(condition)) when null. Since condition is the loop's only termination mechanism, null is rejected before scheduling begins.

Solutions

  1. Pass a terminating predicate delegate, e.g. s => new ValueTask<bool>(s < limit).
  2. Fall back to a default predicate when the configured one is missing (e.g. always-false to generate once, or a count bound).
  3. Validate configuration inputs before composing the operator chain.

Example fix

// before
Generate(observer, 0, configuredCondition /* null */, iterate, select, timing, scheduler);
// after
var condition = configuredCondition ?? (Func<int, ValueTask<bool>>)(s => new ValueTask<bool>(s < 100));
Generate(observer, 0, condition, iterate, select, timing, scheduler);
Defensive patterns

Strategy: validation

Validate before calling

if (condition == null) throw new ArgumentNullException(nameof(condition));

Type guard

bool IsValidCondition<TState>(Func<TState, ValueTask<bool>> f) => f != null;

Try / catch

try { await Generate(observer, state, cond, iterate, select, timing, scheduler); }
catch (ArgumentNullException ex) when (ex.ParamName == "condition") { /* apply a default bounded predicate */ }

Prevention

When it happens

Trigger: Generate(observer, initialState, condition: null, iterate, resultSelector, timeSelector, scheduler) on the 7-argument overload.

Common situations: Predicate built from user configuration that is null when the setting is absent; refactoring between overloads and dropping the condition argument.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Generate.cs:350

                throw new ArgumentNullException(nameof(observer));
            if (condition == null)
                throw new ArgumentNullException(nameof(condition));
            if (iterate == null)
                throw new ArgumentNullException(nameof(iterate));
            if (resultSelector == null)
                throw new ArgumentNullException(nameof(resultSelector));
            if (timeSelector == null)
                throw new ArgumentNullException(nameof(timeSelector));

            return Generate(observer, initialState, condition, iterate, resultSelector, timeSelector, TaskPoolAsyncScheduler.Default);
        }

        public static ValueTask<IAsyncDisposable> Generate<TState, TResult>(IAsyncObserver<TResult> observer, TState initialState, Func<TState, ValueTask<bool>> condition, Func<TState, ValueTask<TState>> iterate, Func<TState, ValueTask<TResult>> resultSelector, Func<TState, ValueTask<TimeSpan>> timeSelector, IAsyncScheduler scheduler)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));
            if (condition == null)
                throw new ArgumentNullException(nameof(condition));
            if (iterate == null)
                throw new ArgumentNullException(nameof(iterate));
            if (resultSelector == null)
                throw new ArgumentNullException(nameof(resultSelector));
            if (timeSelector == null)
                throw new ArgumentNullException(nameof(timeSelector));
            if (scheduler == null)
                throw new ArgumentNullException(nameof(scheduler));

            return scheduler.ScheduleAsync(async ct =>
            {
                var first = true;
                var state = initialState;

                while (!ct.IsCancellationRequested)
                {
                    var hasResult = false;
                    var result = default(TResult);

View on GitHub (pinned to 94b5d5ab91)