dotnet/reactive · error · ArgumentNullException
timeSelector
Error message
timeSelector
What it means
The scheduler-based timed Observable.Generate overload throws ArgumentNullException when timeSelector (Func<TState, DateTimeOffset>) is null. timeSelector yields the absolute due time for each element; without it scheduling is impossible. Validation is eager, thrown synchronously at the call site.
Solutions
- Supply an absolute-time selector, e.g. state => startTime.AddSeconds(state).
- Use the TimeSpan-based overload (relative times) if that matches your data instead.
- Default to a constant increment: state => scheduler.Now.Add(TimeSpan.FromSeconds(1)) when per-state timing is unnecessary.
Example fix
// before var xs = Observable.Generate(0, i => i < 5, i => i + 1, i => i, null, Scheduler.Default); // after var start = DateTimeOffset.Now; var xs = Observable.Generate(0, i => i < 5, i => i + 1, i => i, i => start.AddSeconds(i), Scheduler.Default);
Defensive patterns
Strategy: validation
Validate before calling
if (timeSelector == null)
throw new ArgumentNullException(nameof(timeSelector));
var xs = Observable.Generate(initialState, condition, iterate, resultSelector, timeSelector, scheduler); Type guard
bool HasTimeSelector<TState>(Func<TState, DateTimeOffset> timeSelector) => timeSelector != null;
Try / catch
try
{
var xs = Observable.Generate(state, cond, iter, sel, timeSel, scheduler);
}
catch (ArgumentNullException ex) when (ex.ParamName == "timeSelector")
{
logger.LogError(ex, "Generate timeSelector (DateTimeOffset) was null");
} Prevention
- Do not mix TimeSpan-based and DateTimeOffset-based selector variables; name them clearly (relativeTimeSelector vs absoluteTimeSelector).
- Derive absolute-time selectors from a captured start time so they are always constructible.
- Add unit tests that construct every Generate overload once to catch signature mix-ups.
When it happens
Trigger: Calling Observable.Generate<TState, TResult>(initialState, condition, iterate, resultSelector, timeSelector, scheduler) with timeSelector == null, e.g. when the absolute-time function is derived from user settings that are absent, or an overload mix-up passed a TimeSpan-based selector where DateTimeOffset was expected and the variable stayed null.
Common situations: Switching between the TimeSpan-based and DateTimeOffset-based Generate overloads during migration; calendar/simulation schedulers where the time function comes from injected services that returned null.
Related errors
- action
- action (Parameter 'action')
- action (Parameter 'action')
- action (Value cannot be null)
- ArgumentNullException(nameof(first))
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/16011a8b96a98f81.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Time.cs:760
{
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 s_impl.Generate(initialState, condition, iterate, resultSelector, timeSelector, scheduler);
}
#endregion
#region + Interval +
/// <summary>
/// Returns an observable sequence that produces a value after each period.
/// </summary>
/// <param name="period">Period for producing the values in the resulting sequence. If this value is equal to TimeSpan.Zero, the timer will recur as fast as possible.</param>View on GitHub (pinned to 94b5d5ab91)