apache/dubbo · error · IllegalStateException

<e>

Error message

<e>

What it means

Thrown by MethodConfig.getMethodByName when ReflectUtils.findMethodByMethodName cannot locate the named method on the callback object's class. The underlying exception (typically a NoSuchMethodException wrapper) is re-thrown as an IllegalStateException without a custom message, so only the cause carries detail. It is the leaf cause behind the async-callback resolution failure surfaced by error 341.

Source

Thrown at dubbo-common/src/main/java/org/apache/dubbo/config/MethodConfig.java:312

            if (StringUtils.isNotEmpty(onreturnMethod)) {
                asyncMethodInfo.setOnreturnMethod(getMethodByName(getOnreturn().getClass(), onreturnMethod));
            }

            if (StringUtils.isNotEmpty(onthrowMethod)) {
                asyncMethodInfo.setOnthrowMethod(getMethodByName(getOnthrow().getClass(), onthrowMethod));
            }
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        }

        return asyncMethodInfo;
    }

    private java.lang.reflect.Method getMethodByName(Class<?> clazz, String methodName) {
        try {
            return ReflectUtils.findMethodByMethodName(clazz, methodName);
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }

    /**
     * Set default field values of MethodConfig.
     *
     * @see org.apache.dubbo.config.annotation.Method
     */
    @Override
    protected void checkDefault() {
        super.checkDefault();

        // set default field values
        // org.apache.dubbo.config.annotation.Method.isReturn() default true;
        if (isReturn() == null) {
            setReturn(true);
        }

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Confirm the callback method exists, is public, and is uniquely named (no overload ambiguity) on the callback instance class.
  2. Inspect e.getCause() for the concrete ReflectUtils error message.
  3. Align the annotation/MethodConfig method name with the actual callback method name.

Example fix

// before
public class Callback { public void onInvoke(Object result) {} }
methodConfig.setOninvokeMethod("onInoke"); // typo

// after
methodConfig.setOninvokeMethod("onInvoke");
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate the callback method name resolves uniquely
java.lang.reflect.Method m = ReflectUtils.findMethodByMethodName(callbackInstance.getClass(), methodName);
// if this throws, fix the name before calling convertMethodConfig2AsyncInfo()

Try / catch

try {
    methodConfig.convertMethodConfig2AsyncInfo();
} catch (IllegalStateException e) {
    Throwable root = e.getCause() != null ? e.getCause() : e;
    // root.getMessage() reveals the missing/ambiguous method
    throw new ConfigurationException("Invalid async callback: " + root.getMessage(), root);
}

Prevention

When it happens

Trigger: Calling convertMethodConfig2AsyncInfo where oninvokeMethod/onreturnMethod/onthrowMethod names a method that does not exist (or is not uniquely resolvable) on the getOninvoke()/getOnreturn()/getOnthrow() instance's class.

Common situations: Method name typo in @Method annotation. Callback instance class changed without updating the annotation. Overloaded methods causing ambiguous resolution in ReflectUtils.findFieldByMethodName. Private or package-private callback methods invisible to reflection.

Related errors


AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14). Data as JSON: /api/errors/453dd77fe523f428. Report an issue: GitHub.