dotnet/reactive · error · ArgumentNullException

null

Error message

null

What it means

IAsyncQueryProvider.ExecuteAsync<TResult> on AsyncEnumerableQuery validates the expression tree before executing it asynchronously. It throws ArgumentNullException(nameof(expression)) when the expression is null. This guards the boundary between query composition and async execution.

Solutions

  1. Always pass a non-null Expression (e.g. the queryable's Expression property).
  2. Null-check arguments in the calling layer before invoking the provider.
  3. If translation can yield null, fall back to Expression.Constant of the source before executing.

Example fix

// before
var result = await provider.ExecuteAsync<int>(null, token);
// after
Expression expr = query.Expression ?? Expression.Constant(query);
var result = await provider.ExecuteAsync<int>(expr, token);
Defensive patterns

Strategy: validation

Validate before calling

if (expression == null) throw new InvalidOperationException("expression required before ExecuteAsync");

Type guard

bool IsValid(Expression e) => e is not null;

Try / catch

try { var r = await provider.ExecuteAsync<T>(expr, token); } catch (ArgumentNullException ex) when (ex.ParamName == "expression") { r = await fallbackQuery.ExecuteAsync(token); }

Prevention

When it happens

Trigger: Calling ExecuteAsync<TResult>(null, token) directly, or a provider/infrastructure layer passing a null expression when executing an async queryable.

Common situations: Custom query translation pipelines that can produce a null expression after filtering, mocking frameworks invoking the provider with missing arguments, or reflection-driven execution.

Related errors


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

Appendix: source

Thrown at Ix.NET/Source/System.Linq.Async.Queryable/System/Linq/AsyncEnumerableQuery.cs:103

        /// <param name="expression">The expression tree representing the asynchronous enumerable sequence.</param>
        /// <returns>Asynchronous enumerable sequence represented by the specified expression tree.</returns>
        IAsyncQueryable<TElement> IAsyncQueryProvider.CreateQuery<TElement>(Expression expression)
        {
            return new AsyncEnumerableQuery<TElement>(expression);
        }

        /// <summary>
        /// Executes an expression tree representing a computation over asynchronous enumerable sequences.
        /// </summary>
        /// <typeparam name="TResult">The type of the result of evaluating the expression tree.</typeparam>
        /// <param name="expression">The expression tree to evaluate.</param>
        /// <param name="token">Cancellation token used to cancel the evaluation.</param>
        /// <returns>Task representing the result of evaluating the specified expression tree.</returns>
        ValueTask<TResult> IAsyncQueryProvider.ExecuteAsync<TResult>(Expression expression, CancellationToken token)
        {
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }

            if (!typeof(ValueTask<TResult>).IsAssignableFrom(expression.Type))
            {
                throw new ArgumentException("The specified expression is not assignable to the result type.", nameof(expression));
            }

            return new AsyncEnumerableExecutor<TResult>(expression).ExecuteAsync(token);
        }

        /// <summary>
        /// Gets an enumerator to enumerate the elements in the sequence.
        /// </summary>
        /// <param name="token">Cancellation token used to cancel the enumeration.</param>
        /// <returns>A new enumerator instance used to enumerate the elements in the sequence.</returns>
        public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken token)
        {
            token.ThrowIfCancellationRequested();

View on GitHub (pinned to 94b5d5ab91)