dotnet/reactive · error · ArgumentException

The specified expression is not assignable to the result typ

Error message

The specified expression is not assignable to the result type.

What it means

IAsyncQueryProvider.ExecuteAsync<TResult> requires the expression's static type to be assignable to ValueTask<TResult>, because execution returns ValueTask<TResult>. It throws ArgumentException("The specified expression is not assignable to the result type.", nameof(expression)) when the expression tree's Type does not match, indicating the composed expression and the requested TResult disagree.

Solutions

  1. Align TResult with the expression's result type so expression.Type is assignable to ValueTask<TResult>.
  2. Rebuild the expression with the correct return type (e.g. adjust the final Select/cast in the tree).
  3. If you have Task<TResult> instead, adapt it: new ValueTask<TResult>(task) before forming the expression.

Example fix

// before
var result = await provider.ExecuteAsync<int>(
    Expression.Call(sumLongMethod, source.Expression), token); // Type is ValueTask<long>
// after
var result = await provider.ExecuteAsync<long>(
    Expression.Call(sumLongMethod, source.Expression), token);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!typeof(ValueTask<TResult>).IsAssignableFrom(expression.Type)) throw new InvalidOperationException($"expression type {expression.Type} not assignable to ValueTask<{typeof(TResult)}>");

Type guard

bool IsAssignableToResult<T>(Expression e) => typeof(ValueTask<T>).IsAssignableFrom(e.Type);

Try / catch

try { var r = await provider.ExecuteAsync<T>(expr, token); } catch (ArgumentException ex) when (ex.ParamName == "expression") { // rebuild with corrected TResult r = await provider.ExecuteAsync<CorrectType>(expr, token); }

Prevention

When it happens

Trigger: Calling ExecuteAsync<int> with an expression whose Type is ValueTask<string> (or Task<long>, etc.), or composing FirstAsync/SumAsync-style calls where the element type differs from the TResult supplied to the provider.

Common situations: Type drift after changing an element type (e.g. int to long) without updating the ExecuteAsync call, custom providers returning plain Task expressions, or generic helpers hardcoding an incorrect TResult.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

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

        }

        /// <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();

            if (_enumerable == null)
            {
                var expression = Expression.Lambda<Func<IAsyncEnumerable<T>>>(new AsyncEnumerableRewriter().Visit(_expression), null);
                _enumerable = expression.Compile()();

View on GitHub (pinned to 94b5d5ab91)