dotnet/efcore · error · NotImplementedException

Non-extension static method not supported

Error message

Non-extension static method not supported

What it means

Thrown while emitting the interceptor's first parameter when the reduced operator symbol is a static method that is neither an extension method nor an instance method. The generator handles 'this' extension parameters and instance-method receiver parameters, but a plain non-extension static method has no legal 'this'/'receiver' shape, so it throws NotImplementedException.

Solutions

  1. Use only extension-method LINQ operators (declared with a 'this' first parameter) in precompiled queries.
  2. Wrap the static helper as an extension method so the generator can treat its first parameter as the source.
  3. Exclude that call from the precompiled-query path.
Defensive patterns

Strategy: validation

Validate before calling

// Ensure only extension-method or instance LINQ operators are used
// For each operator in the chain, require reducedSymbol.IsExtensionMethod || (!reducedSymbol.IsStatic).

Try / catch

try { generator.Generate(/*...*/); }
catch (NotImplementedException ex) when (ex.Message.Contains("Non-extension static method"))
{ /* replace the static helper with an extension method or exclude it */ }

Prevention

When it happens

Trigger: A precompiled query chain includes a LINQ operator that resolves to a non-extension static method (i.e. not declared with a 'this' first parameter and not an instance method on the source).

Common situations: Calling helper/static utility methods that look like LINQ operators but are not extension methods; third-party query operators defined as plain static methods.

Related errors


AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11). Data as JSON: /api/errors/09ceb60a101718d1. Report an issue: GitHub.

Appendix: source

Thrown at src/EFCore.Design/Query/Internal/PrecompiledQueryCodeGenerator.cs:719

            for (var i = 0; i < reducedOperatorSymbol.Parameters.Length; i++)
            {
                var parameter = reducedOperatorSymbol.Parameters[i];

                if (i == 0)
                {
                    switch (reducedOperatorSymbol)
                    {
                        case { IsExtensionMethod: true }:
                            code.Append("this ");
                            break;

                        // For instance methods we already added a this parameter above
                        case { IsStatic: false, ReceiverType: not null }:
                            code.Append(", ");
                            break;

                        default:
                            throw new NotImplementedException("Non-extension static method not supported");
                    }
                }
                else
                {
                    code.Append(", ");
                }

                code
                    .Append(_g.TypeExpression(parameter.Type).ToFullString())
                    .Append(' ')
                    .Append(parameter.Name);
            }

            code.AppendLine(")");

            foreach (var f in constraints)
            {
                code.AppendLine(f.NormalizeWhitespace().ToFullString());

View on GitHub (pinned to 3a2006ef56)