dotnet/reactive · error · ArgumentNullException
observableFactory
Error message
observableFactory
What it means
The ValueTask-based overload Defer<TSource>(Func<ValueTask<IAsyncObservable<TSource>>>) (also reached via DeferAsync) throws ArgumentNullException naming 'observableFactory' when the async factory delegate is null. The factory is invoked inside Create at subscription time, so a null must be rejected up front.
Solutions
- Provide a non-null async factory: () => new ValueTask<IAsyncObservable<T>>(source).
- Verify you called the intended overload; use DeferAsync for ValueTask-returning factories.
- Null-check the factory delegate before passing it into Defer/DeferAsync.
Example fix
// before Func<ValueTask<IAsyncObservable<int>>> factory = maybeNull; var xs = AsyncObservable.DeferAsync(factory); // after var xs = AsyncObservable.DeferAsync(factory ?? throw new ArgumentNullException(nameof(factory)));
Defensive patterns
Strategy: validation
Validate before calling
if (observableFactory is null) throw new ArgumentNullException(nameof(observableFactory)); var xs = AsyncObservable.DeferAsync(observableFactory);
Type guard
static bool IsValidAsyncFactory<T>(Func<ValueTask<IAsyncObservable<T>>> f) => f is not null;
Try / catch
try
{
var xs = AsyncObservable.DeferAsync(factory);
}
catch (ArgumentNullException ex) when (ex.ParamName == "observableFactory")
{
// async ValueTask factory was null
} Prevention
- Be explicit about which Defer/DeferAsync overload you intend; avoid relying on overload resolution with nulls.
- Initialize async factory delegates eagerly or mark them 'required'.
- Add Debug.Assert(factory != null) in composition code to catch issues in development.
When it happens
Trigger: Calling AsyncObservable.Defer<TSource>((Func<ValueTask<IAsyncObservable<TSource>>>)null) or DeferAsync<TSource>(null); also calling Defer with a sync Func that the compiler resolved to the ValueTask overload as null.
Common situations: Async factory supplied by a nullable delegate field or DI-resolved function that was never assigned; overload-resolution confusion between the sync, ValueTask, and CancellationToken ValueTask variants of Defer.
Related errors
- Value cannot be null. (Parameter 'observer')
- Value cannot be null. (Parameter 'observableFactory')
- action (Parameter 'action')
- Value cannot be null. (Parameter 'end')
- end
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/35d7c1380f8f5b04.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Defer.cs:26
namespace System.Reactive.Linq
{
public partial class AsyncObservable
{
public static IAsyncObservable<TSource> Defer<TSource>(Func<IAsyncObservable<TSource>> observableFactory)
{
if (observableFactory == null)
throw new ArgumentNullException(nameof(observableFactory));
return Defer(() => new ValueTask<IAsyncObservable<TSource>>(observableFactory()));
}
public static IAsyncObservable<TSource> DeferAsync<TSource>(Func<ValueTask<IAsyncObservable<TSource>>> observableFactory) => Defer(observableFactory);
public static IAsyncObservable<TSource> Defer<TSource>(Func<ValueTask<IAsyncObservable<TSource>>> observableFactory)
{
if (observableFactory == null)
throw new ArgumentNullException(nameof(observableFactory));
return Create<TSource>(async observer =>
{
var source = default(IAsyncObservable<TSource>);
try
{
source = await observableFactory().ConfigureAwait(false);
}
catch (Exception ex)
{
await observer.OnErrorAsync(ex).ConfigureAwait(false);
return AsyncDisposable.Nop;
}
return await source.SubscribeSafeAsync(observer).ConfigureAwait(false);
});
}View on GitHub (pinned to 94b5d5ab91)