dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'observer')
Error message
Value cannot be null. (Parameter 'observer')
What it means
AverageInt32 is the internal AsyncObserver factory that builds the per-item averaging observer for int sequences. It throws ArgumentNullException ('Value cannot be null.', Parameter 'observer') when the downstream IAsyncObserver<double> sink is null. End users normally never call this directly; it is reached through AsyncObserver.Average/Sum-style operators, so a null here means the operator composition passed a null observer internally or you invoked AsyncObserver.AverageInt32 manually with null.
Solutions
- If calling AsyncObserver.AverageInt32 directly, pass the actual downstream IAsyncObserver<double> you received, never null.
- In custom operator code, ensure you forward the observer supplied by SubscribeSafeAsync/Create rather than a separately declared (possibly null) variable.
- Add a null guard before the call and throw a more descriptive exception naming your own operator for easier diagnosis.
- If you hit this via the public Average() operator only, report/check for a library bug — the public surface always passes a non-null observer.
Example fix
// before IAsyncObserver<double> sink = null; var avgObserver = AsyncObserver.AverageInt32(sink); // ArgumentNullException // after IAsyncObserver<double> sink = downstreamObserver ?? throw new ArgumentNullException(nameof(downstreamObserver)); var avgObserver = AsyncObserver.AverageInt32(sink);
Defensive patterns
Strategy: validation
Validate before calling
if (downstream == null) throw new ArgumentNullException(nameof(downstream), "AverageInt32 requires a non-null IAsyncObserver<double>"); var avgObserver = AsyncObserver.AverageInt32(downstream);
Type guard
static bool IsValidObserver(IAsyncObserver<double>? observer) => observer is not null;
Try / catch
try { var obs = AsyncObserver.AverageInt32(downstream); }
catch (ArgumentNullException ex) when (ex.ParamName == "observer") { logger.LogError(ex, "null observer passed to AverageInt32 composition"); throw; } Prevention
- Always forward the observer supplied by SubscribeSafeAsync/Create in custom operators
- Initialize observer mocks in test setup, not lazily
- Use non-nullable observer parameters in your custom operator signatures
- Debug.Assert(observer != null) at composition sites
When it happens
Trigger: Directly calling AsyncObserver.AverageInt32(null) (e.g. building a custom subscription/observer pipeline); writing a custom operator that forwards a null observer into AverageInt32; a mis-implemented CreateAsyncObservable shim that hands a null downstream observer to the operator lambda.
Common situations: Custom operator authors wiring AsyncObserver composition helpers by hand and forgetting to pass the real downstream observer; passing a nullable observer field that was assigned after subscription; copy-pasted operator boilerplate where the observer variable was renamed to a null-valued parameter.
Related errors
- Value cannot be null. (Parameter 'observer')
- Value cannot be null. (Parameter 'observer')
- Value cannot be null. (Parameter 'observer')
- Value cannot be null. (Parameter 'observer')
- Value cannot be null. (Parameter 'selector')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/317c5b3d00a242db.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Average.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 AsyncObserver
{
public static IAsyncObserver<int> AverageInt32(IAsyncObserver<double> observer)
{
if (observer == null)
throw new ArgumentNullException(nameof(observer));
var sum = 0L;
var count = 0L;
return Create<int>(
async x =>
{
try
{
checked
{
sum += x;
count++;
}
}
catch (Exception ex)
{
await observer.OnErrorAsync(ex).ConfigureAwait(false);View on GitHub (pinned to 94b5d5ab91)