{"record":{"id":"5e0420a90ad5210a","repo":"alibaba/spring-ai-alibaba","slug":"protocol-is-null","errorCode":null,"errorMessage":"Protocol is null","messagePattern":"Protocol is null","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"spring-boot-starters/spring-ai-alibaba-starter-config-nacos/src/main/java/com/alibaba/cloud/ai/agent/nacos/tools/NacosMcpGatewayToolCallback.java","lineNumber":428,"sourceCode":"\n\t\t\t// input解析\n\t\t\tlogger.info(\"[call] input string: {}\", input);\n\t\t\tMap<String, Object> args = new HashMap<>();\n\t\t\tif (!input.isEmpty()) {\n\t\t\t\ttry {\n\t\t\t\t\targs = objectMapper.readValue(input, Map.class);\n\t\t\t\t\tlogger.info(\"[call] parsed args: {}\", args);\n\t\t\t\t}\n\t\t\t\tcatch (Exception e) {\n\t\t\t\t\tlogger.error(\"[call] Failed to parse input to args\", e);\n\t\t\t\t\t// 如果解析失败，尝试作为单个参数处理\n\t\t\t\t\targs.put(\"input\", input);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tString protocol = this.toolDefinition.getProtocol();\n\t\t\tif (protocol == null) {\n\t\t\t\tthrow new IllegalStateException(\"Protocol is null\");\n\t\t\t}\n\n\t\t\tif (\"mcp-sse\".equalsIgnoreCase(protocol)) {\n\t\t\t\tMcpServerRemoteServiceConfig remoteServerConfig = this.toolDefinition.getRemoteServerConfig();\n\t\t\t\tif (remoteServerConfig == null) {\n\t\t\t\t\tthrow new IllegalStateException(\"Remote server config is null\");\n\t\t\t\t}\n\t\t\t\treturn handleMcpStreamProtocol(args, remoteServerConfig, protocol);\n\t\t\t}\n\t\t\telse if (\"mcp-streamable\".equalsIgnoreCase(protocol)) {\n\n\t\t\t\tlogger.error(\"[call] Unsupported protocol: {}\", protocol);\n\t\t\t\treturn \"Error: Unsupported protocol \" + protocol;\n\t\t\t\t// McpServerRemoteServiceConfig remoteServerConfig =\n\t\t\t\t// this.toolDefinition.getRemoteServerConfig();\n\t\t\t\t// if (remoteServerConfig == null) {\n\t\t\t\t// throw new IllegalStateException(\"Remote server config is null\");\n\t\t\t\t// }","sourceCodeStart":410,"sourceCodeEnd":446,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-boot-starters/spring-ai-alibaba-starter-config-nacos/src/main/java/com/alibaba/cloud/ai/agent/nacos/tools/NacosMcpGatewayToolCallback.java#L410-L446","documentation":"Thrown by NacosMcpGatewayToolCallback.call when the toolDefinition's protocol field is null. The protocol (e.g. 'mcp-sse', 'http') selects the transport used to invoke the remote tool, so call aborts with IllegalStateException when it is missing.","triggerScenarios":"A ToolDefinition loaded from Nacos whose protocol attribute is absent or null reaches call(); the check occurs right after the null-definition check and before protocol-based dispatch (mcp-sse vs other transports).","commonSituations":"Nacos MCP service registered without the protocol metadata field; typo in the metadata key so the protocol never binds; older Nacos registry entries from before the protocol field was introduced.","solutions":["Set the protocol attribute (e.g. 'mcp-sse' or 'http') in the Nacos MCP service metadata and reload.","Verify the metadata key name matches what the deserializer expects (case/spelling).","Re-register or upgrade stale Nacos service entries that predate the protocol field.","Add a startup-time validation of tool definitions so missing protocols fail before first call."],"exampleFix":"// before (Nacos metadata JSON)\n{\"name\": \"weather-tool\", \"remoteServerConfig\": {...}}\n// after\n{\"name\": \"weather-tool\", \"protocol\": \"mcp-sse\", \"remoteServerConfig\": {...}}","handlingStrategy":"validation","validationCode":"boolean hasProtocol(ToolDefinition td) {\n    return td != null && td.getProtocol() != null && !td.getProtocol().isBlank();\n}\n// check before invoking the tool\n// if (!hasProtocol(toolDefinition)) throw new IllegalStateException(\"Protocol metadata missing in Nacos service descriptor\");","typeGuard":null,"tryCatchPattern":"try {\n    return callback.call(input);\n} catch (IllegalStateException e) {\n    if (\"Protocol is null\".equals(e.getMessage())) {\n        logger.error(\"Tool '{}' from Nacos lacks protocol metadata; re-register the service\", toolName);\n    }\n    throw e;\n}","preventionTips":["Always include the protocol field (e.g. 'mcp-sse') in Nacos MCP service metadata.","Validate loaded tool definitions (name + protocol + remoteServerConfig) at startup.","Watch for schema drift when upgrading Nacos registry entry formats."],"tags":["nacos","mcp","protocol","null-check"],"backgroundTag":"missing-required-config-field","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}