dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'first')
Error message
Value cannot be null. (Parameter 'first')
What it means
SequenceEqual(this first, second) validates both source sequences up front. A null first observable makes the comparison meaningless, so the operator throws ArgumentNullException named 'first' before any subscription occurs.
Solutions
- Ensure the receiver expression is non-null before calling SequenceEqual.
- If the first sequence may be absent, substitute AsyncObservable.Empty<TSource>().
- Guard with a null check and throw a more meaningful exception or return a known result.
- Fix the upstream factory so it never returns null (return an empty observable instead).
Example fix
// before IAsyncObservable<int> left = maybeNull; var eq = left.SequenceEqual(right); // after var eq = (left ?? AsyncObservable.Empty<int>()).SequenceEqual(right);
Defensive patterns
Strategy: validation
Validate before calling
if (first is null) first = AsyncObservable.Empty<TSource>(); if (second is null) second = AsyncObservable.Empty<TSource>();
Type guard
static bool HasSequence<TSource>(IAsyncObservable<TSource>? s) => s is not null;
Try / catch
try { var eq = first.SequenceEqual(second); }
catch (ArgumentNullException ex) when (ex.ParamName == "first") { /* handle missing left sequence */ } Prevention
- Enable nullable reference types so null flows are caught at compile time.
- Never let factories return null observables; return empty sequences.
- Null-check results of nullable lookups before chaining operators.
When it happens
Trigger: Invoking firstObservable.SequenceEqual(secondObservable) where firstObservable is null — typically the result of a factory/lookup method that returned null and is chained with the extension-call syntax.
Common situations: Chaining .SequenceEqual(...) onto a method that can return null (cache miss, dictionary TryGetValue ignored); test fixtures building sequences conditionally.
Related errors
- Value cannot be null. (Parameter 'second')
- Value cannot be null. (Parameter 'comparer')
- Value cannot be null. (Parameter 'observer')
- Value cannot be null. (Parameter 'scheduler')
- Value cannot be null. (Parameter 'source')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/c951036c11c7c3fa.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/SequenceEqual.cs:18
// 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.Disposables;
using System.Threading;
namespace System.Reactive.Linq
{
public partial class AsyncObservable
{
// TODO: Add SequenceEqual<T>(IAsyncObservable<T>, IAsyncEnumerable<T>).
public static IAsyncObservable<bool> SequenceEqual<TSource>(this IAsyncObservable<TSource> first, IAsyncObservable<TSource> second)
{
if (first == null)
throw new ArgumentNullException(nameof(first));
if (second == null)
throw new ArgumentNullException(nameof(second));
return CreateAsyncObservable<bool>.From(
first,
second,
static async (first, second, observer) =>
{
var (firstObserver, secondObserver) = AsyncObserver.SequenceEqual<TSource>(observer);
var firstTask = first.SubscribeSafeAsync(firstObserver);
var secondTask = second.SubscribeSafeAsync(secondObserver);
// REVIEW: Consider concurrent subscriptions.
var d1 = await firstTask.ConfigureAwait(false);
var d2 = await secondTask.ConfigureAwait(false);
View on GitHub (pinned to 94b5d5ab91)