apache/shenyu · critical · IllegalStateException
SDK COMPATIBILITY ERROR: MCP SDK reflection fields are not…
Error message
SDK COMPATIBILITY ERROR: MCP SDK reflection fields are not available. The MCP SDK version may be incompatible with this implementation. Tested SDK version: ${SUPPORTED_SDK_VERSION}. Please verify SDK version compatibility or check logs for field resolution errors. What it means
IllegalStateException from McpSessionHelper.checkReflectionAvailability when the static reflection fields (McpSyncServerExchange.exchange, McpAsyncServerExchange.session) are not resolved even after a retry. These fields are resolved in a static initializer for MCP SDK 0.17.0; if NoSuchFieldException/SecurityException occurred (SDK API change or reflection blocked), all session lookups fail fast with this error.
Solutions
- Check startup logs for 'SDK COMPATIBILITY ERROR: Failed to resolve reflection fields' and the missing field name to identify the exact incompatibility
- Pin io.modelcontextprotocol:mcp to 0.17.0 and Spring AI to 1.1.2, then rebuild the gateway module
- Remove security-manager restrictions or add --add-opens/--add-exports for the MCP SDK packages on JDK 16+
- Upgrade to a ShenYu version whose McpSessionHelper supports your SDK version, or adapt the field names in McpSessionHelper.resolveReflectionFields
Example fix
// before (pom.xml) <mcp.sdk.version>1.0.0</mcp.sdk.version> // after <mcp.sdk.version>0.17.0</mcp.sdk.version>
Defensive patterns
Strategy: validation
Validate before calling
if (!McpSessionHelper.isReflectionAvailable()) {
// refuse to start or route MCP traffic
throw new IllegalStateException("MCP SDK reflection fields unresolved; incompatible SDK version");
} Try / catch
try {
McpSessionHelper.getSessionId(exchange);
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("SDK COMPATIBILITY ERROR")) {
LOG.error("MCP SDK incompatible; tested: " + McpSessionHelper.getSupportedSdkVersion()
+ "; check startup field-resolution logs", e);
} else throw e;
} Prevention
- Call McpSessionHelper.isReflectionAvailable() in a startup health check and fail deployment fast on false
- Pin io.modelcontextprotocol:mcp 0.17.0 and Spring AI 1.1.2 in dependencyManagement
- Verify startup logs show 'MCP SDK reflection fields resolved successfully' before routing MCP traffic
When it happens
Trigger: getSession -> checkReflectionAvailability finds fieldsResolved=false or null field caches, a re-resolve attempt also fails, and the error is thrown before any field access.
Common situations: Dependency upgrade pulling an MCP SDK where the internal fields were renamed/removed; running with a security manager blocking setAccessible at class-init time; native-image or restricted classloader environments where reflection resolution fails — the root cause is logged at startup as 'SDK COMPATIBILITY ERROR: Failed to resolve reflection fields'.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Failed to extract session ID from MCP exchange. This may…
- SDK COMPATIBILITY ERROR: Failed to access SDK internal…
- McpAsyncServerExchange is required in McpSyncServerExchange
- Session is required in McpAsyncServerExchange
- shenyu.jwt.secretKey is not configured. In a multi-instance…
AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12).
Data as JSON: /api/errors/24bf8b7490c782a1.
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:207
}
}
/**
* 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();
}
}
if (!fieldsResolved || Objects.isNull(asyncExchangeFieldCache) || Objects.isNull(sessionFieldCache)) {
throw new IllegalStateException(
"SDK COMPATIBILITY ERROR: MCP SDK reflection fields are not available. "
+ "The MCP SDK version may be incompatible with this implementation. "
+ "Tested SDK version: " + SUPPORTED_SDK_VERSION + ". "
+ "Please verify SDK version compatibility or check logs for field resolution errors.");
}
}
}
/**
* Checks if the SDK reflection fields are available for use.
* This can be used for proactive compatibility checking.
*
* @return true if reflection fields are resolved and available
*/
public static boolean isReflectionAvailable() {
return fieldsResolved && Objects.nonNull(asyncExchangeFieldCache) && Objects.nonNull(sessionFieldCache);
}
View on GitHub (pinned to 567142e072)