dotnet/reactive · error · ArgumentNullException

source

Error message

source

What it means

Dematerialize throws ArgumentNullException when the source IAsyncObservable<Notification<TSource>> is null. The operator converts materialized notifications back into regular OnNext/OnError/OnCompleted signals and validates its source eagerly. A null source is a composition-time programming error.

Solutions

  1. Pass a valid observable of Notification<TSource> (typically the result of Materialize).
  2. Null-check or coalesce the source before applying Dematerialize.
  3. Fix the upstream producer so it returns an empty/failed observable instead of null.

Example fix

// before
var dematerialized = AsyncObservable.Dematerialize(materialized); // materialized == null
// after
if (materialized == null) throw new InvalidOperationException("materialize stage produced no observable");
var dematerialized = AsyncObservable.Dematerialize(materialized);
Defensive patterns

Strategy: validation

Validate before calling

if (materialized is null) throw new InvalidOperationException("materialized source required");
var dematerialized = AsyncObservable.Dematerialize(materialized);

Type guard

bool IsValidSource<T>(IAsyncObservable<Notification<T>>? s) => s is not null;

Try / catch

try
{
    var dematerialized = AsyncObservable.Dematerialize(materialized);
}
catch (ArgumentNullException ex) when (ex.ParamName == "source")
{
    logger.LogError(ex, "Dematerialize called with null source");
    throw;
}

Prevention

When it happens

Trigger: Calling AsyncObservable.Dematerialize(null) or chaining it on a null result of another call.

Common situations: A pipeline stage that materializes notifications returning null on an error path; unit tests constructing the observable lazily and forgetting to assign it.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Dematerialize.cs:12

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

namespace System.Reactive.Linq
{
    public partial class AsyncObservable
    {
        public static IAsyncObservable<TSource> Dematerialize<TSource>(this IAsyncObservable<Notification<TSource>> source)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));

            return Create<Notification<TSource>, TSource>(source, static (source, observer) => source.SubscribeSafeAsync(AsyncObserver.Dematerialize(observer)));
        }
    }

    public partial class AsyncObserver
    {
        public static IAsyncObserver<Notification<TSource>> Dematerialize<TSource>(IAsyncObserver<TSource> observer)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));

            return Create<Notification<TSource>>(
                n => n.AcceptAsync(observer),
                observer.OnErrorAsync,
                observer.OnCompletedAsync
            );
        }

View on GitHub (pinned to 94b5d5ab91)