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
- Ensure the expression's MethodInfo has a DeclaringType: resolve the concrete static method on its real class before composing the tree.
- Avoid building Expression.Call with methods from dynamic/reflection-only sources in async queryables.
- 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
- Build expressions only with MethodInfo resolved from concrete types, not dynamic/reflection-only handles.
- Avoid proxies and IL-emit inside async queryable expression trees.
- Rewrite exotic calls client-side (AsEnumerable) before query execution.
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
- 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')
- Value cannot be null. (Parameter 'onErrorAsync')
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)