dotnet/reactive · error · ArgumentOutOfRangeException
Specified argument was out of the range of valid values. (Pa
Error message
Specified argument was out of the range of valid values. (Parameter 'subscribed')
What it means
TestScheduler.Start throws ArgumentOutOfRangeException for the 'subscribed' parameter when the virtual time at which the subscription happens is earlier than the virtual time at which the observable is created. The test scheduler enforces monotonic virtual timestamps: created <= subscribed <= disposed. It throws so tests with nonsensical time windows fail fast instead of producing misleading results.
Solutions
- Reorder the timestamps so subscribed >= created (and disposed >= subscribed); typically use ReactiveTest.Created and ReactiveTest.Subscribed defaults
- If using Start(create, subscribed, disposed) with custom values, ensure the subscribed value is >= ReactiveTest.Created (200)
- Swap arguments if created/subscribed were transposed by mistake
Example fix
// before var res = scheduler.Start(() => xs, 100, 50, 200); // after var res = scheduler.Start(() => xs, 100, 150, 200); // subscribed (150) >= created (100)
Defensive patterns
Strategy: validation
Validate before calling
// C#
long created = ReactiveTest.Created, subscribed = ReactiveTest.Subscribed;
if (subscribed < created)
throw new ArgumentException("subscribed must be >= created");
var res = scheduler.Start(() => xs, created, subscribed, ReactiveTest.Disposed); Type guard
static bool IsValidWindow(long created, long subscribed, long disposed) =>
created <= subscribed && subscribed <= disposed; Try / catch
try { var res = scheduler.Start(() => xs, created, subscribed, disposed); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "subscribed")
{
// fix timestamps: ensure subscribed >= created
} Prevention
- Default to ReactiveTest.Created/Subscribed/Disposed constants unless you need custom times
- Always order custom timestamps: created <= subscribed <= disposed
- Write a small helper wrapper around Start that clamps/validates the window
When it happens
Trigger: Calling any Start overload (e.g. scheduler.Start(() => xs, created, subscribed, disposed)) with a 'subscribed' value less than the 'created' value, e.g. Start(() => xs, 100, 50, 200) or Start(() => xs, subscribed: 0, ...) after a non-zero created time. Also hit indirectly by the 3-argument Start overload when ReactiveTest.Subscribed (default 200) is less than a custom created value passed in.
Common situations: Hand-written marble tests where the author mixes up the ordering of Created (200), Subscribed (300), Disposed (1000) defaults and passes custom values in the wrong order; refactoring tests with custom virtual timestamps; copying a Start call and editing timestamps so subscribed < created.
Related errors
- Specified argument was out of the range of valid values. (Pa
- Specified argument was out of the range of valid values. (Pa
- Specified argument was out of the range of valid values. (Pa
- count
- duration
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/9edd27de55dab9f8.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/Microsoft.Reactive.Testing/TestScheduler.cs:93
/// <typeparam name="T">The element type of the observable sequence being tested.</typeparam>
/// <param name="create">Factory method to create an observable sequence.</param>
/// <param name="created">Virtual time at which to invoke the factory to create an observable sequence.</param>
/// <param name="subscribed">Virtual time at which to subscribe to the created observable sequence.</param>
/// <param name="disposed">Virtual time at which to dispose the subscription.</param>
/// <returns>Observer with timestamped recordings of notification messages that were received during the virtual time window when the subscription to the source sequence was active.</returns>
/// <exception cref="ArgumentNullException"><paramref name="create"/> is null.</exception>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="subscribed"/> is less than <paramref name="created"/>.</exception>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="disposed"/> is less than <paramref name="created"/> or <paramref name="subscribed"/>.</exception>
public ITestableObserver<T> Start<T>(Func<IObservable<T>> create, long created, long subscribed, long disposed)
{
if (create == null)
{
throw new ArgumentNullException(nameof(create));
}
if (subscribed < created)
{
throw new ArgumentOutOfRangeException(nameof(subscribed));
}
if (disposed < created || disposed < subscribed)
{
throw new ArgumentOutOfRangeException(nameof(disposed));
}
var source = default(IObservable<T>);
var subscription = default(IDisposable);
var observer = CreateObserver<T>();
ScheduleAbsolute(default(object), created, (scheduler, state) => { source = create(); return Disposable.Empty; });
ScheduleAbsolute(default(object), subscribed, (scheduler, state) => { subscription = source.Subscribe(observer); return Disposable.Empty; });
ScheduleAbsolute(default(object), disposed, (scheduler, state) => { subscription.Dispose(); return Disposable.Empty; });
Start();
return observer;
}View on GitHub (pinned to 94b5d5ab91)