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
- Always pass a non-null Expression (e.g. the queryable's Expression property).
- Null-check arguments in the calling layer before invoking the provider.
- 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
- Pass query.Expression (never a possibly-null custom expression) to ExecuteAsync.
- Null-check translation outputs before invoking the provider.
- Cover the null-expression path in provider unit tests.
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
- Value cannot be null. (Parameter 'func')
- Value cannot be null. (Parameter 'resultSelector')
- Value cannot be null. (Parameter 'observer')
- observableFactory
- new ArgumentNullException(nameof(comparer))
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)