dotnet/reactive · error · ArgumentNullException
new ArgumentNullException(nameof(iterate))
Error message
new ArgumentNullException(nameof(iterate))
What it means
AsyncReactive's Generate operator throws ArgumentNullException when the iterate (state-advance) delegate is null. Generate requires every per-iteration callback (condition, iterate, resultSelector, timeSelector) to advance/emit values; a null iterate would make the state machine unable to progress past the first element, so it is rejected eagerly before scheduling.
Solutions
- Pass a non-null iterate delegate, e.g. s => new ValueTask<TState>(s + 1) or an equivalent method group.
- If iterate is optional in your design, supply an identity function s => new ValueTask<TState>(s) instead of null.
- Check the expression producing the delegate (ternary, config-driven lookup) and guard it before calling Generate.
Example fix
// before Func<int, ValueTask<int>> iterate = maybeStep; // null await AsyncObservable.Generate(observer, 0, s => new ValueTask<bool>(s < 10), iterate, ...); // after var iterate = maybeStep ?? (s => new ValueTask<int>(s + 1)); await AsyncObservable.Generate(observer, 0, s => new ValueTask<bool>(s < 10), iterate, ...);
Defensive patterns
Strategy: validation
Validate before calling
if (iterate == null) throw new ArgumentNullException(nameof(iterate));
Type guard
static bool IsValidGenerateArgs<TState, TResult>(Func<TState, ValueTask<bool>> cond, Func<TState, ValueTask<TState>> iter, Func<TState, ValueTask<TResult>> sel, Func<TState, ValueTask<TimeSpan>> time, IAsyncScheduler sched) => cond != null && iter != null && sel != null && time != null && sched != null;
Try / catch
try { var d = await Generate(observer, 0, cond, iter, sel, timeSel, sched); } catch (ArgumentNullException ex) { /* ex.ParamName == "iterate" */ } Prevention
- Never pass nullable delegate variables into Generate; coalesce with ?? identity.
- Wrap Generate in a project-local factory that validates all arguments once.
- Enable nullable reference types (NonNullTypes) so null delegate flows are flagged at compile time.
When it happens
Trigger: Calling the fully-async overload AsyncRx.NET/System.Reactive.Async/Linq/Operators/Generate.cs:345 (Generate(observer, initialState, condition, iterate, resultSelector, timeSelector, scheduler) with ValueTask-returning delegates) passing null for the Func<TState, ValueTask<TState>> iterate parameter, typically via a ternary or variable that resolves to null.
Common situations: Building a timed generator where the iterate lambda is conditionally assigned; passing a method group whose target is null; refactoring from Rx's Generate where iterate was optional or inferred and porting to System.Reactive.Async where it is mandatory.
Related errors
- new ArgumentNullException(nameof(resultSelector))
- new ArgumentNullException(nameof(timeSelector))
- new ArgumentNullException(nameof(scheduler))
- Value cannot be null. (Parameter 'disposable1')
- Value cannot be null. (Parameter 'disposable2')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/412376c901c992c6.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Generate.cs:352
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);
var nextDue = default(TimeSpan);
View on GitHub (pinned to 94b5d5ab91)