apache/shenyu · critical · IllegalStateException
SDK COMPATIBILITY ERROR: Failed to access SDK internal…
Error message
SDK COMPATIBILITY ERROR: Failed to access SDK internal fields via reflection. This indicates the MCP SDK API has changed. Tested SDK version: ${SUPPORTED_SDK_VERSION}. Error: ${e.getMessage()} What it means
IllegalStateException thrown from McpSessionHelper.getSession's catch (IllegalAccessException) block, wrapped as an 'SDK COMPATIBILITY ERROR'. Field.get() via reflection can throw IllegalAccessException when setAccessible was blocked (security manager, JPMS module encapsulation) or the cached Field no longer matches the class; this indicates the MCP SDK API/layout changed or reflection is restricted. The message includes the tested SDK version (0.17.0) and the original error.
Solutions
- Pin io.modelcontextprotocol:mcp to 0.17.0 (and Spring AI 1.1.2) and rebuild
- Add JVM flags to open the SDK packages, e.g. --add-opens io.modelcontextprotocol.spec/...=ALL-UNNAMED, if module encapsulation blocks access
- Remove/disable the security manager or grant ReflectPermission("suppressAccessChecks") in your environment
- Upgrade the ShenYu mcp-server plugin to a release tested against your SDK version instead of relying on reflection
Example fix
// before (java args) java -jar shenyu-bootstrap.jar // after java --add-opens io.modelcontextprotocol.spec/io.modelcontextprotocol.spec=ALL-UNNAMED -jar shenyu-bootstrap.jar
Defensive patterns
Strategy: try-catch
Validate before calling
if (!McpSessionHelper.isReflectionAvailable()) {
throw new IllegalStateException("Reflection blocked for MCP SDK; tested version " + McpSessionHelper.getSupportedSdkVersion());
} Try / catch
try {
String id = McpSessionHelper.getSessionId(exchange);
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("SDK COMPATIBILITY ERROR")) {
LOG.error("MCP SDK reflection denied; check JDK module opens/security manager", e.getCause());
} else throw e;
} Prevention
- Avoid security managers in the gateway JVM
- Add --add-opens flags for io.modelcontextprotocol packages on JDK 16+
- Pin SDK 0.17.0 and re-run integration tests after any JDK upgrade
When it happens
Trigger: asyncExchangeFieldCache.get(...) or sessionFieldCache.get(...) throws IllegalAccessException during getSession — reflection access to MCP SDK internals is denied at read time even though field resolution succeeded earlier.
Common situations: Upgrading the MCP SDK past 0.17.0 so field access is denied; running under a Java security manager or with strong module encapsulation (--illegal-access denied); JDK upgrade tightening reflective access to the SDK package.
Understand the failure class
Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.
Related errors
- Failed to extract session ID from MCP exchange. This may…
- SDK COMPATIBILITY ERROR: MCP SDK reflection fields are not…
- McpAsyncServerExchange is required in McpSyncServerExchange
- Session is required in McpAsyncServerExchange
- Import mcp server config failed:
AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12).
Data as JSON: /api/errors/2dd8da2fc103427f.
Report an issue: GitHub.
Appendix: source
Thrown at shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/session/McpSessionHelper.java:184
* @return the McpServerSession instance
* @throws IllegalStateException if SDK reflection fails (API incompatibility)
*/
public static McpServerSession getSession(final McpSyncServerExchange mcpSyncServerExchange) {
checkReflectionAvailability();
try {
Object asyncExchange = asyncExchangeFieldCache.get(mcpSyncServerExchange);
if (Objects.isNull(asyncExchange)) {
throw new IllegalArgumentException("McpAsyncServerExchange is required in McpSyncServerExchange");
}
McpAsyncServerExchange mcpAsyncServerExchange = (McpAsyncServerExchange) asyncExchange;
Object session = sessionFieldCache.get(mcpAsyncServerExchange);
if (Objects.isNull(session)) {
throw new IllegalArgumentException("Session is required in McpAsyncServerExchange");
}
return (McpServerSession) session;
} catch (IllegalAccessException e) {
throw new IllegalStateException(
"SDK COMPATIBILITY ERROR: Failed to access SDK internal fields via reflection. "
+ "This indicates the MCP SDK API has changed. "
+ "Tested SDK version: " + SUPPORTED_SDK_VERSION + ". "
+ "Error: " + e.getMessage(), e);
}
}
/**
* Checks if reflection fields are available and throws an informative exception if not.
*
* @throws IllegalStateException if reflection fields are not available
*/
private static void checkReflectionAvailability() {
if (!fieldsResolved || Objects.isNull(asyncExchangeFieldCache) || Objects.isNull(sessionFieldCache)) {
// Attempt to re-resolve fields in case of delayed class loading
synchronized (FIELD_RESOLVE_LOCK) {
if (!fieldsResolved) {
resolveReflectionFields();View on GitHub (pinned to 567142e072)