dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'observer')
Error message
Value cannot be null. (Parameter 'observer')
What it means
This ArgumentNullException is thrown by AsyncObserver.SumInt32(IAsyncObserver<int>) when the downstream observer is null. This is a lower-level factory in System.Reactive.Async that builds the aggregation observer; it's normally called by the Sum operator but can be invoked directly in custom operator or observer-composition code. The parameter 'observer' names the null argument.
Solutions
- Pass a valid IAsyncObserver<int>, e.g. one built via CreateObserver or obtained from your subscription pipeline.
- In custom Subscribe implementations, validate the observer argument and throw ArgumentNullException early (matching this library's behavior).
- If a factory returns the observer, check it for null before composing SumInt32 around it.
Example fix
// before
var sumObserver = AsyncObserver.SumInt32(_downstream); // _downstream may be null
// after
if (_downstream == null)
throw new InvalidOperationException("Downstream observer not attached");
var sumObserver = AsyncObserver.SumInt32(_downstream); Defensive patterns
Strategy: try-catch
Validate before calling
if (downstream is null)
throw new ArgumentNullException(nameof(downstream)); Type guard
static bool HasObserver<T>(IAsyncObserver<T>? o) => o is not null;
Try / catch
try { var obs = AsyncObserver.SumInt32(downstream); }
catch (ArgumentNullException ex) when (ex.ParamName == "observer")
{
throw new InvalidOperationException("Observer pipeline not attached before SumInt32", ex);
} Prevention
- Always terminate observer chains with a concrete sink before wrapping with aggregation observers.
- Add the standard guard clause to custom Subscribe implementations.
- Configure test mocks to return non-null observers by default.
When it happens
Trigger: Calling AsyncObserver.SumInt32(null) directly, or implementing a custom Create/Subscribe path that forwards a null observer (e.g. a custom IAsyncObservable whose Subscribe receives and passes through a null observer).
Common situations: Hit by authors of custom async-reactive operators, adapters wrapping other observer frameworks, or test code constructing observers piecemeal where the downstream observer was never created or a mock returned null.
Related errors
- Value cannot be null. (Parameter 'onNextAsync')
- Value cannot be null. (Parameter 'observer')
- null (Parameter 'observer')
- Value cannot be null. (Parameter 'observer')
- Value cannot be null. (Parameter 'observer')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/e621e4dfb7fdc184.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Sum.cs:14
// 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.Threading.Tasks;
namespace System.Reactive.Linq
{
public partial class AsyncObserver
{
public static IAsyncObserver<int> SumInt32(IAsyncObserver<int> observer)
{
if (observer == null)
throw new ArgumentNullException(nameof(observer));
var sum = 0;
return Create<int>(
async x =>
{
try
{
checked
{
sum += x;
}
}
catch (Exception ex)
{
await observer.OnErrorAsync(ex).ConfigureAwait(false);
}
},View on GitHub (pinned to 94b5d5ab91)