dotnet/reactive · error · ArgumentException
Expected Qbservable.ToQueryable.
Error message
Expected Qbservable.ToQueryable.
What it means
CreateQuery on the IQbservable<T>->IQueryable bridge provider only accepts expression trees whose single method call is Qbservable.ToQueryable. Any other expression shape or method is rejected with ArgumentException because the provider cannot translate it back to an IQbservable pipeline. This is a guard for an internal conversion pattern (observable.AsQbservable().<operators>.ToEnumerable().AsQueryable()).
Solutions
- Only call CreateQuery with the result of an AsQbservable().ToQueryable() expression tree; use observable.AsQbservable() and operators on IQbservable directly instead of Queryable operators
- Check the expression before passing: it must be a MethodCallExpression with Method.DeclaringType == typeof(Qbservable) and Method.Name == nameof(Qbservable.ToQueryable)
- Perform filtering/transformation on the IQbservable<T> side before converting to IQueryable
Example fix
// before
IQueryable<int> q = provider.CreateQuery(Expression.Call(typeof(Queryable), "Where", new[]{typeof(int)}, source.Expression, predicate));
// after
IQueryable<int> q = source.AsQbservable().Where(x => x > 0).ToEnumerable().AsQueryable(); Defensive patterns
Strategy: validation
Validate before calling
if (expr is not MethodCallExpression mc || mc.Method.DeclaringType != typeof(Qbservable) || mc.Method.Name != nameof(Qbservable.ToQueryable)) throw new ArgumentException("Only Qbservable.ToQueryable expressions are supported", nameof(expr)); Type guard
static bool IsToQueryableCall(Expression e) => e is MethodCallExpression c && c.Method.DeclaringType == typeof(Qbservable) && c.Method.Name == nameof(Qbservable.ToQueryable);
Prevention
- Build the queryable only via observable.AsQbservable().ToQueryable(), never hand-constructed expression trees
- Apply operators on the IQbservable<T>, not the IQueryable view
- Assert the expression shape in unit tests before calling CreateQuery
When it happens
Trigger: Calling IQueryProvider.CreateQuery with an expression that is not a MethodCallExpression, whose declaring type is not Qbservable, or whose method name is not ToQueryable — e.g. composing Queryable operators directly on the queryable without going through AsQbservable().
Common situations: Developers manually building expression trees against an ExpressionViewModel/IQueryable view of an IQbservable, or using LINQ query syntax over the wrapped queryable with operators the bridge does not recognize.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- There is no method '{0}' on type '{1}' that matches the spec
- selector
- source
- Value cannot be null. (Parameter 'elementSelector')
- nameof(predicate)
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/f50421668f8b0840.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/ObservableQuery.cs:53
IQueryable<TElement> IQueryProvider.CreateQuery<TElement>(Expression expression)
{
//
// Here we're on the edge between IQbservable and IQueryable for the local
// execution case. E.g.:
//
// observable.AsQbservable().<operators>.ToQueryable()
//
// This should be turned into a local execution, with the push-to-pull
// adapter in the middle, so we rewrite to:
//
// observable.AsQbservable().<operators>.ToEnumerable().AsQueryable()
//
if (expression is not MethodCallExpression call ||
call.Method.DeclaringType != typeof(Qbservable) ||
call.Method.Name != nameof(Qbservable.ToQueryable))
{
throw new ArgumentException(Strings_Providers.EXPECTED_TOQUERYABLE_METHODCALL, nameof(expression));
}
//
// This is the IQbservable<T> object corresponding to the lhs. Now wrap
// it in two calls to get the local queryable.
//
var arg0 = call.Arguments[0];
var res =
Expression.Call(
AsQueryable.MakeGenericMethod(typeof(TElement)),
Expression.Call(
typeof(Observable).GetMethod(nameof(Observable.ToEnumerable))!.MakeGenericMethod(typeof(TElement)),
arg0
)
);
//
// Queryable operator calls should be taken care of by the provider forView on GitHub (pinned to 94b5d5ab91)