baomidou/mybatis-plus · error · MybatisPlusException

Failed to extract Groovy lambda meta from proxy handler: {}

Error message

Failed to extract Groovy lambda meta from proxy handler: {}

What it means

The generic failure branch of GroovyLambdaMeta: getDelegate()/getMethod()/getOwner() were found, but invoking them (or casting the result) threw — IllegalAccessException, InvocationTargetException, or ClassCastException. The handler has the expected shape but the calls fail (security/visibility) or return unexpected types, wrapped as MybatisPlusException('Failed to extract Groovy lambda meta from proxy handler: <handler class>').

Source

Thrown at mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/support/GroovyLambdaMeta.java:54

    private final Class<?> clazz;
    private final String name;

    public GroovyLambdaMeta(Proxy func) {
        InvocationHandler handler = Proxy.getInvocationHandler(func);
        try {
            Method getDelegate = handler.getClass().getMethod("getDelegate");
            Object delegate = getDelegate.invoke(handler);
            Method getMethod = delegate.getClass().getMethod("getMethod");
            this.name = (String) getMethod.invoke(delegate);
            Method getOwner = delegate.getClass().getMethod("getOwner");
            Object owner = getOwner.invoke(delegate);
            this.clazz = (owner instanceof Class) ? (Class<?>) owner : owner.getClass();
        } catch (NoSuchMethodException e) {
            throw new MybatisPlusException("Unsupported proxy type for Groovy lambda extraction: "
                + handler.getClass().getName()
                + ". Expected a Groovy ConvertedClosure handler exposing getDelegate().", e);
        } catch (Exception e) {
            throw new MybatisPlusException("Failed to extract Groovy lambda meta from proxy handler: "
                + handler.getClass().getName(), e);
        }
    }

    @Override
    public String getImplMethodName() {
        return name;
    }

    @Override
    public Class<?> getInstantiatedClass() {
        return clazz;
    }

    @Override
    public String toString() {
        return clazz.getSimpleName() + "::" + name;
    }

View on GitHub (pinned to bf67d90747)

Solutions

  1. Check the suppressed cause (ex) — IllegalAccessException points to visibility, InvocationTargetException to a failing delegate, ClassCastException to a wrong method-name type.
  2. Normalize the Groovy version: one consistent groovy artifact across the build, matching what the project's mybatis-plus version tests against.
  3. Avoid closure-based wrappers in the affected Groovy code; use explicit column-name conditions.
  4. Upgrade mybatis-plus to pick up fixes in Groovy lambda metadata extraction.
Defensive patterns

Strategy: try-catch

Try / catch

try {
    LambdaQueryWrapper<T> w = Wrappers.lambdaQuery(Entity.class)
        .eq(closureAsSFunction(Entity::getName), val);
} catch (MybatisPlusException e) {
    Throwable cause = e.getCause(); // IllegalAccessException / InvocationTargetException / CCE
    wrapper.eq("name", val); // degrade to column-name condition
}

Prevention

When it happens

Trigger: Groovy closure delegate methods exist but are not public/accessible (IllegalAccessException), the delegate's getMethod() invocation fails at runtime (InvocationTargetException from a broken closure), or getMethod() does not return a String (ClassCastException on the (String) cast of the method name).

Common situations: Groovy security restrictions or non-public synthetic delegate classes under certain Groovy versions; closures compiled with @CompileStatic or Grape-loaded scripts whose delegate returns nonstandard method metadata; mixed Groovy artifact versions on the classpath (groovy jar mismatch).

Related errors


AI-assisted analysis of baomidou/mybatis-plus@bf67d90747 (2026-08-14). Data as JSON: /api/errors/1324a946aecd59b1. Report an issue: GitHub.