dotnet/reactive · error · InvalidOperationException
There is no method '{0}' on type '{1}' that matches the spec
Error message
There is no method '{0}' on type '{1}' that matches the specified arguments. What it means
FindObservableMethod rewrites a Queryable method call to the corresponding Qbservable operator. When no overload on the target type matches the argument list (checked via ArgsMatch), it throws InvalidOperationException 'There is no method {0} on type {1} that matches the specified arguments'. This means the query expression contains a call the IQbservable side has no compatible operator for.
Solutions
- Rewrite the query to use only operators/overloads available on IQbservable/Qbservable with matching signatures
- Replace index-based or multi-parameter overloads (e.g. Func<T,int,bool>) with supported single-parameter forms
- Perform the unsupported transformation after ToEnumerable()/AsQueryable() on the local queryable
- Inspect the failing method name and targetType in the message and compare overloads on Qbservable
Example fix
// before source.AsQbservable().Where((x, i) => i > 0).ToEnumerable().AsQueryable() // after source.AsQbservable().Where(x => x > 0).ToEnumerable().AsQueryable()
Defensive patterns
Strategy: validation
Validate before calling
var candidate = typeof(Qbservable).GetMethods().Any(m => m.Name == methodName && ParametersCompatible(m, args)); if (!candidate) throw new NotSupportedException($"No Qbservable operator '{methodName}' matches the given arguments"); Type guard
static bool HasObservableOperator(string name, params Type[] argTypes) => typeof(Qbservable).GetMethods(BindingFlags.Public | BindingFlags.Static).Any(m => m.Name == name && m.GetParameters().Length == argTypes.Length + 1);
Try / catch
try { return provider.CreateQuery(expr); } catch (InvalidOperationException ex) when (ex.Message.Contains("no method")) { throw new NotSupportedException($"Operator not supported on IQbservable: {ex.Message}"); } Prevention
- Use only overloads that exist identically on Queryable and Qbservable (same parameter shapes)
- Avoid index-based lambdas and custom extension methods inside bridged queries
- Compare your operator signature against Qbservable's public API when writing bridged queries
When it happens
Trigger: A Queryable expression tree contains a method call whose name exists on Qbservable but whose parameter types/counts do not match any overload — e.g. custom projections, extra predicates, unsupported operator signatures (like Queryable.Where with an index-based predicate that Qbservable lacks), or generic type argument mismatches.
Common situations: Mixing standard LINQ operators not mirrored by Qbservable, passing lambdas with different arity (e.g. (x, i) => ...) into a bridged query, or library upgrades where signatures diverged.
Related errors
- Expected Qbservable.ToQueryable.
- 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/59f378d923841f31.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/ObservableQuery.cs:403
else
{
targetType = method.DeclaringType!; // NB: These methods were found from a declaring type.
if (targetType.IsDefined(typeof(LocalQueryMethodImplementationTypeAttribute), false))
{
var mapping = (LocalQueryMethodImplementationTypeAttribute)targetType.GetCustomAttributes(typeof(LocalQueryMethodImplementationTypeAttribute), false)[0];
targetType = mapping.TargetType;
}
methods = GetMethods(targetType);
}
//
// From all the operators with the method's name, find the one that matches all arguments.
//
var typeArgs = method.IsGenericMethod ? method.GetGenericArguments() : null;
var targetMethod = methods[method.Name].FirstOrDefault(candidateMethod => ArgsMatch(candidateMethod, arguments, typeArgs))
?? throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings_Providers.NO_MATCHING_METHOD_FOUND, method.Name, targetType.Name));
//
// Restore generic arguments.
//
if (typeArgs != null)
{
targetMethod = targetMethod.MakeGenericMethod(typeArgs);
}
//
// Finally, we need to deal with mismatches on Expression<Func<...>> versus Func<...>.
//
var parameters = targetMethod.GetParameters();
for (int i = 0, n = parameters.Length; i < n; i++)
{
arguments[i] = Unquote(arguments[i]);
}
View on GitHub (pinned to 94b5d5ab91)