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
- Align TResult with the expression's result type so expression.Type is assignable to ValueTask<TResult>.
- Rebuild the expression with the correct return type (e.g. adjust the final Select/cast in the tree).
- 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
- Derive TResult from expression.Type instead of hardcoding it in generic helpers.
- Re-check result types after changing element types in the query.
- Add a debug assertion comparing expression.Type against ValueTask<TResult> before execution.
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
- null
- Could not find method with name '{0}' on type '{1}'.
- Could not find a matching method with name '{0}' on type '{1
- Value cannot be null. (Parameter 'onErrorAsync')
- Value cannot be null. (Parameter 'onNextAsync')
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)