dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'source')

Error message

Value cannot be null. (Parameter 'source')

What it means

System.ArgumentNullException thrown by PublishLast<TSource>(source) in PublishLast.cs:17, with Parameter 'source'. PublishLast multicasts only the final element via SequentialAsyncAsyncSubject and, like Publish, eagerly rejects a null IAsyncObservable<TSource> before Multicast is invoked.

Solutions

  1. Ensure a valid non-null observable is passed to PublishLast; trace the null-producing assignment.
  2. Substitute AsyncObservable.Empty<TSource>() when a missing source is an expected condition.
  3. Check the code that builds the source (factory, await result, field init) and add your own null guard with a meaningful message.

Example fix

// before
IAsyncObservable<int> source = null;
var last = source.PublishLast();

// after
var source = await GetSourceAsync() ?? AsyncObservable.Empty<int>();
var last = source.PublishLast();
Defensive patterns

Strategy: validation

Validate before calling

if (source is null) throw new InvalidOperationException("Cannot PublishLast: source observable is null");
var last = source.PublishLast();

Type guard

static bool HasSource<T>(IAsyncObservable<T>? s) => s is not null;

Try / catch

try { var last = source.PublishLast(); }
catch (ArgumentNullException ex) when (ex.ParamName == "source") { /* fallback: AsyncObservable.Empty<TSource>().PublishLast() or rethrow with context */ }

Prevention

When it happens

Trigger: Calling source.PublishLast() where source is null, e.g. an IAsyncObservable<T> variable that was never assigned or a producer that returned null.

Common situations: Aggregating 'last value' semantics over a stream whose source comes from an async service that returned null; test scaffolding without a source; pipeline composition where an earlier operator returned null instead of throwing.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/PublishLast.cs:17

// 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. 

using System.Reactive.Subjects;
using System.Threading.Tasks;

namespace System.Reactive.Linq
{
    // REVIEW: Expose PublishLast using ConcurrentAsyncAsyncSubject<T> underneath.

    public partial class AsyncObservable
    {
        public static IConnectableAsyncObservable<TSource> PublishLast<TSource>(this IAsyncObservable<TSource> source)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));

            return Multicast(source, new SequentialAsyncAsyncSubject<TSource>());
        }

        public static IAsyncObservable<TResult> PublishLast<TSource, TResult>(this IAsyncObservable<TSource> source, Func<IAsyncObservable<TSource>, IAsyncObservable<TResult>> selector)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (selector == null)
                throw new ArgumentNullException(nameof(selector));

            return Multicast(source, () => new SequentialAsyncAsyncSubject<TSource>(), selector);
        }

        public static IAsyncObservable<TResult> PublishLast<TSource, TResult>(this IAsyncObservable<TSource> source, Func<IAsyncObservable<TSource>, ValueTask<IAsyncObservable<TResult>>> selector)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));

View on GitHub (pinned to 94b5d5ab91)