dotnet/reactive · error · NotSupportedException

Could not rewrite method with name '{0}' without a Declaring

Error message

Could not rewrite method with name '{0}' without a DeclaringType.

What it means

AsyncEnumerableRewriter.VisitMethodCall rewrites IQueryable method calls into their async IAsyncEnumerable equivalents. To find the replacement it needs the method's DeclaringType; when the node's method has no declaring type it throws NotSupportedException("Could not rewrite method with name '{0}' without a DeclaringType."). This is an internal invariant: queryable operators always come from a declaring type.

Solutions

  1. Ensure the expression's MethodInfo has a DeclaringType: resolve the concrete static method on its real class before composing the tree.
  2. Avoid building Expression.Call with methods from dynamic/reflection-only sources in async queryables.
  3. Handle the custom call before query execution — rewrite or replace it so the rewriter never sees it.

Example fix

// before
var call = Expression.Call(dynMethod, arg); // dynMethod.DeclaringType == null
var q = source.Provider.CreateQuery<int>(call);
// after
var concrete = typeof(KnownOps).GetMethod(nameof(KnownOps.MyOp));
var call = Expression.Call(concrete, arg);
var q = source.Provider.CreateQuery<int>(call);
Defensive patterns

Strategy: validation

Validate before calling

if (node.Method.DeclaringType == null) throw new InvalidOperationException($"Method '{node.Method.Name}' lacks a DeclaringType and cannot be rewritten");

Type guard

bool IsRewritable(MethodCallExpression n) => n.Method.DeclaringType is not null;

Try / catch

try { var rewritten = rewriter.Visit(node); } catch (NotSupportedException ex) when (ex.Message.Contains("without a DeclaringType")) { // execute client-side instead result = source.AsEnumerable().Select(...); }

Prevention

When it happens

Trigger: An expression tree containing a MethodCall node whose Method.DeclaringType is null reaching the rewriter — typically from hand-built or reflection-emitted expressions, dynamic method handles, or trimmed/proxied methods.

Common situations: Constructing custom Expression.Call nodes with MethodInfo obtained via reflection on dynamic proxies, IL-emit scenarios, or expression manipulation libraries that strip declaring types.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at Ix.NET/Source/System.Linq.Async.Queryable/System/Linq/AsyncEnumerableRewriter.cs:89

            }

            MethodInfo method;

            //
            // Find a corresponding method in the non-expression world, e.g. rewriting from
            // the AsyncQueryable methods to the ones on AsyncEnumerable.
            //
            if (declType == typeof(AsyncQueryable))
            {
                method = FindEnumerableMethod(node.Method.Name, args, typeArgs);
                args = FixupQuotedArgs(method, args);
                return Expression.Call(obj, method, args);
            }
            else
            {
                if (declType == null)
                {
                    throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture, "Could not rewrite method with name '{0}' without a DeclaringType.", node.Method.Name));
                }

                method = FindMethod(declType, node.Method.Name, args, typeArgs, BindingFlags.Static | (node.Method.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic));
                args = FixupQuotedArgs(method, args);
            }

            return Expression.Call(obj, method, args);
        }

        protected override Expression VisitLambda<T>(Expression<T> node)
        {
            //
            // Don't recurse into lambdas; all the ones returning IAsyncQueryable<T>
            // are compatible with their IAsyncEnumerable<T> counterparts due to the
            // covariant return type.
            //
            return node;
        }

View on GitHub (pinned to 94b5d5ab91)