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

  1. Rewrite the query to use only operators/overloads available on IQbservable/Qbservable with matching signatures
  2. Replace index-based or multi-parameter overloads (e.g. Func<T,int,bool>) with supported single-parameter forms
  3. Perform the unsupported transformation after ToEnumerable()/AsQueryable() on the local queryable
  4. 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

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


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)