dotnet/reactive · error · ArgumentNullException

nameof(scheduler)

Error message

nameof(scheduler)

What it means

This is an ArgumentNullException thrown by AsyncObservable.Empty(IAsyncScheduler) when the scheduler argument is null. This overload exists to control where the completion signal is scheduled; without a scheduler the library cannot dispatch, so the null is rejected immediately. It is a fail-fast guard on the factory method.

Solutions

  1. Pass a concrete scheduler, e.g. ImmediateAsyncScheduler.Instance or the library's default scheduler
  2. Fix the DI registration / factory returning a null scheduler
  3. Use the parameterless AsyncObservable.Empty<TSource>() overload if no custom scheduling is needed

Example fix

// before
var empty = AsyncObservable.Empty<int>(GetScheduler()); // returns null
// after
var sched = GetScheduler() ?? ImmediateAsyncScheduler.Instance;
var empty = AsyncObservable.Empty<int>(sched);
Defensive patterns

Strategy: validation

Validate before calling

if (scheduler is null) throw new ArgumentNullException(nameof(scheduler));
var empty = AsyncObservable.Empty<int>(scheduler);

Type guard

bool HasScheduler(IAsyncScheduler s) => s is not null;

Try / catch

try { var empty = AsyncObservable.Empty<int>(scheduler); }
catch (ArgumentNullException ex) when (ex.ParamName == "scheduler") { /* fall back to ImmediateAsyncScheduler.Instance */ }

Prevention

When it happens

Trigger: Calling AsyncObservable.Empty<TSource>(null), e.g. a scheduler resolved from DI/config that was not registered, or a variable assigned from a lookup that returned null.

Common situations: DI containers missing an IAsyncScheduler registration; choosing a scheduler via a config switch whose branch forgets assignment; tests where a scheduler mock was never set.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Empty.cs:20

// The .NET Foundation licenses this file to you under the MIT License.
// See the LICENSE file in the project root for more information. 

using System.Reactive.Concurrency;
using System.Threading.Tasks;

namespace System.Reactive.Linq
{
    public partial class AsyncObservable
    {
        public static IAsyncObservable<TSource> Empty<TSource>()
        {
            return Create<TSource>(observer => AsyncObserver.Empty(observer));
        }

        public static IAsyncObservable<TSource> Empty<TSource>(IAsyncScheduler scheduler)
        {
            if (scheduler == null)
                throw new ArgumentNullException(nameof(scheduler));

            return Create<TSource>(observer => AsyncObserver.Empty(observer, scheduler));
        }
    }

    public partial class AsyncObserver
    {
        public static ValueTask<IAsyncDisposable> Empty<TSource>(IAsyncObserver<TSource> observer) => Empty(observer, ImmediateAsyncScheduler.Instance);

        public static ValueTask<IAsyncDisposable> Empty<TSource>(IAsyncObserver<TSource> observer, IAsyncScheduler scheduler)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));
            if (scheduler == null)
                throw new ArgumentNullException(nameof(scheduler));

            return scheduler.ScheduleAsync(async ct =>
            {

View on GitHub (pinned to 94b5d5ab91)