{"record":{"id":"82c61fd2c61a4f77","repo":"spring-projects/spring-ai","slug":"failed-to-access-tool-method","errorCode":null,"errorMessage":"Failed to access tool method","messagePattern":"Failed to access tool method","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/tool/AbstractMcpToolMethodCallback.java","lineNumber":80,"sourceCode":"\t\tthis.toolMethod = toolMethod;\n\t\tthis.toolObject = toolObject;\n\t\tthis.returnMode = returnMode;\n\t}\n\n\t/**\n\t * Invokes the tool method with the provided arguments.\n\t * @param methodArguments The arguments to pass to the method\n\t * @return The result of the method invocation\n\t * @throws IllegalStateException if the method cannot be accessed\n\t * @throws RuntimeException if there's an error invoking the method\n\t */\n\tprotected Object callMethod(Object[] methodArguments) {\n\t\tthis.toolMethod.setAccessible(true);\n\t\ttry {\n\t\t\treturn this.toolMethod.invoke(this.toolObject, methodArguments);\n\t\t}\n\t\tcatch (IllegalAccessException ex) {\n\t\t\tthrow new RuntimeException(\"Failed to access tool method\", ex);\n\t\t}\n\t\tcatch (InvocationTargetException ex) {\n\t\t\tThrowable cause = ex.getCause();\n\t\t\tif (cause instanceof RuntimeException re) {\n\t\t\t\tthrow re;\n\t\t\t}\n\t\t\tif (cause instanceof Error err) {\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t\tthrow new UndeclaredThrowableException(cause);\n\t\t}\n\t}\n\n\t/**\n\t * Builds the method arguments from the context, tool input arguments, and optionally\n\t * the full request.\n\t * @param exchangeOrContext The exchange or context object (e.g.,\n\t * McpSyncServerExchange, McpAsyncServerExchange, or McpTransportContext)","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/tool/AbstractMcpToolMethodCallback.java#L62-L98","documentation":"AbstractMcpToolMethodCallback.callMethod throws RuntimeException('Failed to access tool method', cause IllegalAccessException) when the reflective toolMethod.invoke call is denied — the JVM cannot access the (possibly non-public) method even after setAccessible(true), typically due to module restrictions or visibility issues. The original IllegalAccessException is preserved as the cause.","triggerScenarios":"Invoking a private/package-private tool method from a different package or a Java module that does not open its package to the framework; running under JPMS or a hardened SecurityManager/agent policy.","commonSituations":"Tool methods on classes in java.* or other strongly-encapsulated modules; JDK 16+ strong encapsulation breaking reflection on internal APIs; tool beans in modularized libraries.","solutions":["Make the tool method public (and its class public)","Add JVM args like --add-opens=<module>/<package>=ALL-UNNAMED for the encapsulated package","Keep tool beans on the classpath (unnamed module) rather than inside named modules","Check for SecurityManager/policy blocks on reflective access"],"exampleFix":"// before\nprivate String myTool(String arg) { ... }\n// after\npublic String myTool(String arg) { ... }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    result = callback.call(request);\n} catch (RuntimeException e) {\n    if (e.getCause() instanceof IllegalAccessException iae) {\n        log.error(\"Tool method not accessible: {}\", iae.getMessage(), iae);\n    }\n    throw e;\n}","preventionTips":["Declare tool methods public in public classes","Avoid exposing tools from strongly encapsulated JDK/internal modules","Add --add-opens flags when reflection on named modules is unavoidable"],"tags":["reflection","access","tool"],"backgroundTag":"permission-denied","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}