dotnet/reactive · error · ArgumentNullException

Argument cannot be null (Parameter name: actionAsync)

Error message

Argument cannot be null (Parameter name: actionAsync)

What it means

This FromAsync overload wraps a Func<Task> action into an async observable and throws ArgumentNullException immediately when actionAsync is null. The delegate is required since there is no meaningful asynchronous action to subscribe to otherwise. Validation happens eagerly at call time, not at subscription.

Solutions

  1. Pass a valid Task-returning delegate, e.g. FromAsync(() => DoWorkAsync()).
  2. Guard the delegate before the call: if (actionAsync == null) throw/return default pipeline.
  3. If the action may be absent, use Defer or an empty observable instead of FromAsync with null.

Example fix

// before
Func<Task> action = GetAction(); // may return null
var xs = AsyncObservable.FromAsync(action);
// after
var xs = action != null ? AsyncObservable.FromAsync(action) : AsyncObservable.Empty<Unit>();
Defensive patterns

Strategy: validation

Validate before calling

if (actionAsync is null) throw new InvalidOperationException("actionAsync delegate required");

Type guard

bool HasAction(Func<Task> a) => a is not null;

Try / catch

try { var xs = AsyncObservable.FromAsync(actionAsync); }
catch (ArgumentNullException ex) when (ex.ParamName == "actionAsync") { xs = AsyncObservable.Empty<Unit>(); }

Prevention

When it happens

Trigger: Calling AsyncObservable.FromAsync((Func<Task>)null) or passing a Task-returning delegate variable that was never assigned (e.g. a method group resolved via reflection or an uninitialized field).

Common situations: Conditional wiring of pipelines where the action delegate is picked from a dictionary/config and the key is missing, or passing the result of a factory method that returned null.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/FromAsync.cs:52

                throw new ArgumentNullException(nameof(functionAsync));

            return Defer(() => StartAsync(functionAsync));
        }

        public static IAsyncObservable<TResult> FromAsync<TResult>(Func<CancellationToken, ValueTask<TResult>> functionAsync, IAsyncScheduler scheduler)
        {
            if (functionAsync == null)
                throw new ArgumentNullException(nameof(functionAsync));
            if (scheduler == null)
                throw new ArgumentNullException(nameof(scheduler));

            return Defer(() => StartAsync(functionAsync, scheduler));
        }

        public static IAsyncObservable<Unit> FromAsync(Func<Task> actionAsync)
        {
            if (actionAsync == null)
                throw new ArgumentNullException(nameof(actionAsync));

            return Defer(() => StartAsync(actionAsync));
        }

        public static IAsyncObservable<Unit> FromAsync(Func<Task> actionAsync, IAsyncScheduler scheduler)
        {
            if (actionAsync == null)
                throw new ArgumentNullException(nameof(actionAsync));
            if (scheduler == null)
                throw new ArgumentNullException(nameof(scheduler));

            return Defer(() => StartAsync(actionAsync, scheduler));
        }

        public static IAsyncObservable<Unit> FromAsync(Func<CancellationToken, Task> actionAsync)
        {
            if (actionAsync == null)
                throw new ArgumentNullException(nameof(actionAsync));

View on GitHub (pinned to 94b5d5ab91)