dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'values')

Error message

Value cannot be null. (Parameter 'values')

What it means

In Append(observer, IAsyncScheduler, IEnumerable<TSource>), the values sequence is enumerated and each element is scheduled to the observer after the source completes; a null sequence cannot be enumerated so the factory throws ArgumentNullException (long .NET form: "Value cannot be null. (Parameter 'values')"). Observer and values are validated before the scheduler, so this fires when observer and values state allow the values check to run with a null sequence.

Solutions

  1. Pass a non-null IEnumerable (Enumerable.Empty<TSource>() when nothing to append).
  2. Coalesce: Append(observer, scheduler, values ?? Enumerable.Empty<TSource>()).
  3. Fix the producer so it returns empty collections, never null.

Example fix

// before
AsyncObservable.Append(observer, scheduler, (IEnumerable<int>)null);
// after
AsyncObservable.Append(observer, scheduler, values ?? Enumerable.Empty<int>());
Defensive patterns

Strategy: validation

Validate before calling

if (values is null) values = Enumerable.Empty<TSource>();
var (obs, disp) = AsyncObservable.Append(observer, scheduler, values);

Type guard

bool HasValues<T>(IEnumerable<T>? v) => v is not null;

Try / catch

try { var (obs, disp) = AsyncObservable.Append(observer, scheduler, values); }
catch (ArgumentNullException ex) when (ex.ParamName == "values") { var (obs, disp) = AsyncObservable.Append(observer, scheduler, Enumerable.Empty<TSource>()); }

Prevention

When it happens

Trigger: AsyncObservable.Append(observer, scheduler, null) where the third argument (IEnumerable<TSource> values) is null — typically a null list, array, or LINQ result.

Common situations: Config-driven value list that failed to load; dictionary/TryGetValue result null; a service method returning null instead of an empty collection; test fixtures with an unset sequence field.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Append.cs:267

                observer.OnErrorAsync,
                async () =>
                {
                    foreach (var value in values)
                    {
                        await observer.OnNextAsync(value).ConfigureAwait(false);
                    }

                    await observer.OnCompletedAsync().ConfigureAwait(false);
                }
            );
        }

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

            var d = new SingleAssignmentAsyncDisposable();

            return
                (
                    Create<TSource>(
                        observer.OnNextAsync,
                        observer.OnErrorAsync,
                        async () =>
                        {
                            var task = await scheduler.ScheduleAsync(async ct =>
                            {
                                var e = default(IEnumerator<TSource>);

                                try
                                {

View on GitHub (pinned to 94b5d5ab91)