dotnet/reactive · error · ArgumentNullException

Argument cannot be null (Parameter name: functionAsync)

Error message

Argument cannot be null (Parameter name: functionAsync)

What it means

The parameterless-scheduler FromAsync overload throws ArgumentNullException when functionAsync is null. FromAsync converts an async function into an IAsyncObservable that emits one result, and it validates the function eagerly so the error surfaces at the factory call rather than at subscribe time.

Solutions

  1. Pass a non-null function, e.g. AsyncObservable.FromAsync(() => new ValueTask<int>(Compute())).
  2. Guard when the function is optional: if (fn != null) var obs = AsyncObservable.FromAsync(fn);
  3. Fix the delegate source (DI registration, factory match) so it never yields null.

Example fix

// before
Func<ValueTask<int>> fn = null;
var obs = AsyncObservable.FromAsync(fn);
// after
Func<ValueTask<int>> fn = () => new ValueTask<int>(42);
var obs = AsyncObservable.FromAsync(fn);
Defensive patterns

Strategy: validation

Validate before calling

// C#
if (functionAsync == null) throw new ArgumentNullException(nameof(functionAsync));
var obs = AsyncObservable.FromAsync(functionAsync);

Type guard

static bool IsValid<TResult>(Func<ValueTask<TResult>> fn) => fn != null;

Try / catch

try { var obs = AsyncObservable.FromAsync(fn); }
catch (ArgumentNullException ex) when (ex.ParamName == "functionAsync") { /* resolve/assign the function */ }

Prevention

When it happens

Trigger: Calling AsyncObservable.FromAsync((Func<ValueTask<TResult>>)null); storing the ValueTask-returning function in a nullable delegate that was never assigned; conditional handler selection resolving to null.

Common situations: Switching from Task-returning methods to ValueTask and leaving the delegate reference null; strategy/factory patterns where no strategy matched; reflection-created delegates that failed to bind.

Related errors


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

Appendix: source

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

// 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.Reactive.Concurrency;
using System.Threading;
using System.Threading.Tasks;

namespace System.Reactive.Linq
{
    public partial class AsyncObservable
    {
        public static IAsyncObservable<TResult> FromAsync<TResult>(Func<ValueTask<TResult>> functionAsync)
        {
            if (functionAsync == null)
                throw new ArgumentNullException(nameof(functionAsync));

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

        public static IAsyncObservable<TResult> FromAsync<TResult>(Func<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<TResult> FromAsync<TResult>(Func<CancellationToken, ValueTask<TResult>> functionAsync)
        {
            if (functionAsync == null)
                throw new ArgumentNullException(nameof(functionAsync));

View on GitHub (pinned to 94b5d5ab91)