dotnet/reactive · error · ArgumentNullException

source

Error message

source

What it means

SkipLast's first overload throws ArgumentNullException("source") when the IAsyncObservable<TSource> it is called on is null. The library validates the source sequence at the public entry point before doing any work. Since SkipLast is an extension method, calling it on a null reference is possible in C# and produces this error instead of a NullReferenceException.

Solutions

  1. Ensure the source sequence is non-null before calling SkipLast; use AsyncObservable.Empty<TSource>() as a fallback.
  2. Fix the upstream producer so it never returns null (return an empty sequence instead).
  3. Coalesce at the call site: source ?? AsyncObservable.Empty<T>().SkipLast(n).

Example fix

// before
return cached.SkipLast(10); // cached may be null
// after
return (cached ?? AsyncObservable.Empty<TValue>()).SkipLast(10);
Defensive patterns

Strategy: validation

Validate before calling

if (source == null) source = AsyncObservable.Empty<TSource>();
var res = source.SkipLast(count);

Type guard

static bool IsNonNull<T>(IAsyncObservable<T> s) => s != null;

Try / catch

try { var res = src.SkipLast(n); }
catch (ArgumentNullException ex) when (ex.ParamName == "source") { var res = AsyncObservable.Empty<TSource>(); }

Prevention

When it happens

Trigger: Invoking nullSource.SkipLast(3) or SkipLast(null, 3) where the source IAsyncObservable is null, typically because a factory method or a previous operator returned null.

Common situations: A helper method returning null instead of an empty observable; conditional initialization leaving the sequence field unset; passing the result of a dictionary lookup that missed.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/SkipLast.cs:16

// 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.Collections.Generic;
using System.Reactive.Concurrency;
using System.Threading.Tasks;

namespace System.Reactive.Linq
{
    public partial class AsyncObservable
    {
        public static IAsyncObservable<TSource> SkipLast<TSource>(this IAsyncObservable<TSource> source, int count)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (count < 0)
                throw new ArgumentOutOfRangeException(nameof(count));

            if (count == 0)
            {
                return source;
            }

            return CreateAsyncObservable<TSource>.From(
                source,
                count,
                static (source, count, observer) => source.SubscribeSafeAsync(AsyncObserver.SkipLast(observer, count)));
        }


        public static IAsyncObservable<TSource> SkipLast<TSource>(this IAsyncObservable<TSource> source, TimeSpan duration)
        {
            if (source == null)

View on GitHub (pinned to 94b5d5ab91)