{"record":{"id":"d3a5012f84437e81","repo":"apache/dubbo","slug":"e-getmessage","errorCode":null,"errorMessage":"<e.getMessage()>","messagePattern":"<e\\.getMessage\\(\\)>","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"dubbo-common/src/main/java/org/apache/dubbo/config/MethodConfig.java","lineNumber":302,"sourceCode":"\n        asyncMethodInfo.setOninvokeInstance(getOninvoke());\n        asyncMethodInfo.setOnreturnInstance(getOnreturn());\n        asyncMethodInfo.setOnthrowInstance(getOnthrow());\n\n        try {\n            if (StringUtils.isNotEmpty(oninvokeMethod)) {\n                asyncMethodInfo.setOninvokeMethod(getMethodByName(getOninvoke().getClass(), oninvokeMethod));\n            }\n\n            if (StringUtils.isNotEmpty(onreturnMethod)) {\n                asyncMethodInfo.setOnreturnMethod(getMethodByName(getOnreturn().getClass(), onreturnMethod));\n            }\n\n            if (StringUtils.isNotEmpty(onthrowMethod)) {\n                asyncMethodInfo.setOnthrowMethod(getMethodByName(getOnthrow().getClass(), onthrowMethod));\n            }\n        } catch (Exception e) {\n            throw new IllegalStateException(e.getMessage(), e);\n        }\n\n        return asyncMethodInfo;\n    }\n\n    private java.lang.reflect.Method getMethodByName(Class<?> clazz, String methodName) {\n        try {\n            return ReflectUtils.findMethodByMethodName(clazz, methodName);\n        } catch (Exception e) {\n            throw new IllegalStateException(e);\n        }\n    }\n\n    /**\n     * Set default field values of MethodConfig.\n     *\n     * @see org.apache.dubbo.config.annotation.Method\n     */","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/apache/dubbo/blob/3a3043227f5571d25eb2889de5bca22f2914843b/dubbo-common/src/main/java/org/apache/dubbo/config/MethodConfig.java#L284-L320","documentation":"Thrown by MethodConfig.convertMethodConfig2AsyncInfo when resolving the oninvoke/onreturn/onthrow callback methods fails for any reason. The original exception's message is propagated but wrapped in an IllegalStateException, masking the concrete type. It almost always indicates a misconfigured async callback (missing method, wrong signature, or null callback instance).","triggerScenarios":"Configuring a MethodConfig with oninvoke/onreturn/onthrow method names whose target method does not exist on the corresponding callback object, or when the callback object (getOninvoke()/getOnreturn()/getOnthrow()) is null while its method name is set. The wrapping catch in convertMethodConfig2AsyncInfo re-throws any failure from getMethodByName.","commonSituations":"Typo in the oninvoke/onreturn/onthrow method name. Method signature mismatch (e.g. wrong parameter/return type). Setting oninvokeMethod without setting the oninvoke instance. Renaming a callback method in the implementation but not in the @Method annotation.","solutions":["Verify the oninvoke/onreturn/onthrow method name exactly matches a public method on the callback instance, including signature.","Ensure the oninvoke/onreturn/onthrow instance fields are set (not null) when the corresponding method-name fields are set.","Check the original cause via getCause() on the IllegalStateException to see the underlying ReflectUtils error (e.g. NoSuchMethodException)."],"exampleFix":"// before\n@Method(name = \"sayHello\", oninvoke = \"cb\", oninvokeMethod = \"onInoke\") // typo\n\n// after\n@Method(name = \"sayHello\", oninvoke = \"cb\", oninvokeMethod = \"onInvoke\") // matches actual method","handlingStrategy":"validation","validationCode":"// Validate callback methods exist before triggering convertMethodConfig2AsyncInfo\nprivate void validateCallback(Object instance, String methodName) {\n    if (instance == null && methodName != null && !methodName.isEmpty()) {\n        throw new IllegalArgumentException(\"Callback instance missing for method \" + methodName);\n    }\n    if (instance != null && methodName != null && !methodName.isEmpty()) {\n        ReflectUtils.findMethodByMethodName(instance.getClass(), methodName); // fail fast\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    AsyncMethodInfo info = methodConfig.convertMethodConfig2AsyncInfo();\n} catch (IllegalStateException e) {\n    // cause carries the real reason (NoSuchMethodException, etc.)\n    Throwable root = e.getCause() != null ? e.getCause() : e;\n    log.error(\"Async callback config invalid for method {}: {}\", methodConfig.getName(), root.getMessage());\n    throw e;\n}","preventionTips":["Set the oninvoke/onreturn/onthrow instance whenever the corresponding method name is set.","Use compile-time-checked callback method references instead of String names where possible.","Add a startup self-test that resolves each callback method via reflection."],"tags":["async-callback","reflection","config"],"backgroundTag":null,"analyzedSha":"3a3043227f5571d25eb2889de5bca22f2914843b","analyzedAt":"2026-08-14T00:43:19.853Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}