dotnet/reactive · error · ArgumentNullException
new ArgumentNullException(nameof(timeSelector))
Error message
new ArgumentNullException(nameof(timeSelector))
What it means
The fully-async Generate overload throws ArgumentNullException when the timeSelector delegate is null. timeSelector computes the per-element delay (TimeSpan in this overload); a null value would leave the scheduler with no delay to apply between OnNext emissions, so it is rejected upfront.
Solutions
- Supply a timeSelector, e.g. s => new ValueTask<TimeSpan>(TimeSpan.FromSeconds(1)).
- If no delay is desired, pass s => new ValueTask<TimeSpan>(TimeSpan.Zero) instead of null.
- Double-check which Generate overload you are calling and switch to the non-timed overload if you do not need per-element delays.
Example fix
// before Generate(observer, 0, cond, iter, sel, null, sched); // throws // after Generate(observer, 0, cond, iter, sel, s => new ValueTask<TimeSpan>(TimeSpan.FromSeconds(1)), sched);
Defensive patterns
Strategy: validation
Validate before calling
if (timeSelector == null) throw new ArgumentNullException(nameof(timeSelector));
Type guard
static bool HasTimeSelector<TState>(Func<TState, ValueTask<TimeSpan>> ts) => ts is not null;
Try / catch
try { await Generate(observer, state, cond, iter, sel, timeSel, sched); } catch (ArgumentNullException ex) when (ex.ParamName == "timeSelector") { /* fall back to TimeSpan.Zero selector */ } Prevention
- Use s => new ValueTask<TimeSpan>(TimeSpan.Zero) for no-delay generators rather than null.
- Keep TimeSpan vs DateTimeOffset overloads straight; verify argument types match the overload.
- Centralize delay policies in one non-null factory function.
When it happens
Trigger: Calling Generate(observer, initialState, condition, iterate, resultSelector, timeSelector, scheduler) with ValueTask delegates (Generate.cs:345) and passing null for Func<TState, ValueTask<TimeSpan>> timeSelector.
Common situations: Confusing overloads: the TimeSpan-based overload requires timeSelector while non-timed variants do not, so copying a call from a non-timed overload omits it; a delay-strategy object whose ToSelector() returned null.
Related errors
- new ArgumentNullException(nameof(scheduler))
- nameof(scheduler)
- Argument cannot be null (Parameter name: scheduler)
- Value cannot be null. (Parameter 'scheduler')
- new ArgumentNullException(nameof(iterate))
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/a1b2359a2fd156f0.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Generate.cs:356
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);
try
{
if (first)
{View on GitHub (pinned to 94b5d5ab91)