{"record":{"id":"7e5dd209347ad658","repo":"alibaba/nacos","slug":"legacy-a2a-endpoint-address-must-not-be-empty","errorCode":null,"errorMessage":"Legacy A2A Endpoint address must not be empty","messagePattern":"Legacy A2A Endpoint address must not be empty","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"ai/src/main/java/com/alibaba/nacos/ai/service/a2a/CanonicalA2aEndpointOperationService.java","lineNumber":229,"sourceCode":"        }\n    }\n    \n    private String childClientId(String parentClientId, String namespaceId, String agentName,\n        String version) {\n        String identity = parentClientId + CHILD_ID_SEPARATOR + namespaceId + CHILD_ID_SEPARATOR\n            + agentName + CHILD_ID_SEPARATOR + version;\n        return CHILD_CLIENT_ID_PREFIX\n            + UUID.nameUUIDFromBytes(identity.getBytes(StandardCharsets.UTF_8));\n    }\n    \n    private Service composeService(String namespaceId, String agentName) {\n        return Service.newService(namespaceId, Constants.Agent.AGENT_ENDPOINT_GROUP,\n            RadServiceNameComposer.compose(agentName, A2A_PROTOCOL));\n    }\n    \n    private Instance toInstance(AgentEndpoint source) {\n        if (StringUtils.isBlank(source.getAddress())) {\n            throw new IllegalArgumentException(\"Legacy A2A Endpoint address must not be empty\");\n        }\n        Endpoint endpoint = new Endpoint();\n        endpoint.setUri(composeUri(source));\n        endpoint.setTransport(source.getTransport());\n        return AgentRuntimeEndpointMapper.toLegacyA2aInstance(endpoint, source.getVersion(),\n            source.getProtocolVersion(), source.getTenant());\n    }\n    \n    private String composeUri(AgentEndpoint endpoint) {\n        String protocol = StringUtils.isBlank(endpoint.getProtocol())\n            ? AiConstants.A2a.A2A_ENDPOINT_DEFAULT_PROTOCOL : endpoint.getProtocol();\n        if (AiConstants.A2a.A2A_ENDPOINT_DEFAULT_PROTOCOL.equalsIgnoreCase(protocol)\n            && endpoint.isSupportTls()) {\n            protocol = \"https\";\n        }\n        String address = endpoint.getAddress();\n        String host = address != null && address.indexOf(':') >= 0 && !address.startsWith(\"[\")\n            ? '[' + address + ']' : address;","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/ai/src/main/java/com/alibaba/nacos/ai/service/a2a/CanonicalA2aEndpointOperationService.java#L211-L247","documentation":"Thrown (as NacosApiException INVALID_PARAM via invalidEndpoint wrapper) when toInstance detects a blank address on an AgentEndpoint in a legacy A2A batch. Each endpoint must have a non-blank address to compose a valid URI for the Naming instance. The original IllegalArgumentException is caught in register() and re-thrown with PARAMETER_VALIDATE_ERROR.","triggerScenarios":"Calling register with an AgentEndpoint whose getAddress() is null, empty, or whitespace-only. Endpoint list deserialized from JSON where the 'address' field was missing or empty. Endpoint object constructed without setting the address.","commonSituations":"Client-side bug where address is populated from a config that was not loaded. Endpoint auto-discovery producing entries with blank addresses for unhealthy instances. JSON schema drift where the address field was renamed but the deserializer still expects 'address'.","solutions":["Filter out or reject endpoints with blank addresses before calling register.","Ensure every AgentEndpoint in the batch has setAddress() called with a non-blank host/IP.","Validate the endpoint collection client-side: for each e, assert StringUtils.isNotBlank(e.getAddress())."],"exampleFix":"// before\nendpoints.add(new AgentEndpoint()); // address not set\nendpointOpService.register(parentClientId, ns, agentName, endpoints);\n\n// after\nList<AgentEndpoint> valid = endpoints.stream()\n    .filter(e -> StringUtils.isNotBlank(e.getAddress()))\n    .toList();\nif (valid.isEmpty()) {\n    throw new IllegalArgumentException(\"No endpoints with valid address\");\n}\nendpointOpService.register(parentClientId, ns, agentName, valid);","handlingStrategy":"validation","validationCode":"// Filter out endpoints with blank addresses before registering\nList<AgentEndpoint> valid = endpoints.stream()\n    .filter(e -> e != null && StringUtils.isNotBlank(e.getAddress()))\n    .toList();\nif (valid.isEmpty()) {\n    throw new IllegalArgumentException(\"No endpoints with valid address\");\n}\nendpointOpService.register(parentClientId, ns, agentName, valid);","typeGuard":"public static boolean allEndpointsHaveAddress(Collection<AgentEndpoint> endpoints) {\n    if (endpoints == null || endpoints.isEmpty()) {\n        return false;\n    }\n    return endpoints.stream().allMatch(\n        e -> e != null && StringUtils.isNotBlank(e.getAddress()));\n}","tryCatchPattern":"try {\n    endpointOpService.register(parentClientId, ns, agentName, endpoints);\n} catch (NacosApiException e) {\n    if (e.getDetailErrCode() == ErrorCode.PARAMETER_VALIDATE_ERROR.getCode()\n            && e.getMessage().contains(\"address must not be empty\")) {\n        // filter and retry\n        var valid = endpoints.stream()\n            .filter(e -> StringUtils.isNotBlank(e.getAddress())).toList();\n        endpointOpService.register(parentClientId, ns, agentName, valid);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Always set address on every AgentEndpoint before adding to the batch.","Add a client-side filter to drop blank-address entries.","Validate endpoint collections before any register call."],"tags":["a2a","endpoint","validation","address","invalid-param"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}