{"record":{"id":"0b1206a115b2c2d9","repo":"alibaba/nacos","slug":"online-agent-version-must-contain-callinterfaces","errorCode":null,"errorMessage":"Online Agent Version must contain callInterfaces","messagePattern":"Online Agent Version must contain callInterfaces","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"ai/src/main/java/com/alibaba/nacos/ai/service/agent/AgentPersistenceService.java","lineNumber":1058,"sourceCode":"            && !agent.getAgentName().equals(initialVersion.getAgentName())) {\n            throw new IllegalArgumentException(\"initialVersion agentName does not match Agent\");\n        }\n        if (initialVersion.getStatus() != null\n            && !expectedStatus.equals(initialVersion.getStatus())) {\n            throw new IllegalArgumentException(\"initialVersion status must be \" + expectedStatus);\n        }\n    }\n    \n    private void validateOnlineVersionInputs(String namespaceId, String agentName,\n        AgentVersionDetail version, String preferredLatest) {\n        AgentValidationUtils.validateNamespaceId(namespaceId);\n        AgentValidationUtils.validateAgentName(agentName);\n        if (version == null) {\n            throw new IllegalArgumentException(\"Agent Version must not be null\");\n        }\n        AgentValidationUtils.validateVersion(version.getVersion());\n        if (version.getCallInterfaces() == null) {\n            throw new IllegalArgumentException(\"Online Agent Version must contain callInterfaces\");\n        }\n        if (version.getNamespaceId() != null\n            && !namespaceId.equals(version.getNamespaceId())) {\n            throw new IllegalArgumentException(\"Agent Version namespaceId does not match request\");\n        }\n        if (version.getAgentName() != null && !agentName.equals(version.getAgentName())) {\n            throw new IllegalArgumentException(\"Agent Version agentName does not match request\");\n        }\n        if (version.getStatus() != null\n            && !AiConstants.Agent.VERSION_STATUS_ONLINE.equals(version.getStatus())) {\n            throw new IllegalArgumentException(\"Agent Version status must be online\");\n        }\n        if (version.getContentDigest() != null || version.getCreateTime() != null\n            || version.getUpdateTime() != null) {\n            throw new IllegalArgumentException(\n                \"Agent Version must not contain read-only projection fields\");\n        }\n        if (preferredLatest != null && !version.getVersion().equals(preferredLatest)) {","sourceCodeStart":1040,"sourceCodeEnd":1076,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/ai/src/main/java/com/alibaba/nacos/ai/service/agent/AgentPersistenceService.java#L1040-L1076","documentation":"An Agent Version that will be persisted directly as 'online' must include a non-null callInterfaces list. This guard in validateOnlineVersionInputs runs before createOnlineVersion writes the Version row, guaranteeing that a published online Version carries at least one protocol endpoint contract so it can be discovered and invoked.","triggerScenarios":"Calling createOnlineVersion (the internal direct-online Agent Version creation path, reachable from the HTTP direct-online flow POST /v3/admin/ai/agent/draft or the client publish API) with an AgentVersionDetail whose getCallInterfaces() returns null.","commonSituations":"A client SDK or migration tool builds an AgentVersionDetail for direct-online creation and forgets to populate callInterfaces. A test fixture constructs a Version with only version/author metadata. The toOnlineVersion(request) converter received a request whose callInterfaces were null (normally caught earlier by validateDirectOnlineRequest at line 775).","solutions":["Set version.setCallInterfaces(...) with at least one AgentCallInterface before calling createOnlineVersion.","If using the HTTP direct-online API, ensure the request JSON body includes a non-null callInterfaces array.","Verify the upstream AgentDraftCreateRequest carries callInterfaces — validateDirectOnlineRequest rejects null callInterfaces first."],"exampleFix":"// before\nAgentVersionDetail v = new AgentVersionDetail();\nv.setVersion(\"1.0.0\");\npersistenceService.createOnlineVersion(ns, name, v, null); // throws\n\n// after\nv.setCallInterfaces(List.of(callInterface));\npersistenceService.createOnlineVersion(ns, name, v, null);","handlingStrategy":"validation","validationCode":"if (version == null || version.getCallInterfaces() == null || version.getCallInterfaces().isEmpty()) {\n    throw new IllegalArgumentException(\"Online Agent Version requires callInterfaces\");\n}","typeGuard":"boolean hasCallInterfaces(AgentVersionDetail v) {\n    return v != null && v.getCallInterfaces() != null && !v.getCallInterfaces().isEmpty();\n}","tryCatchPattern":"try {\n    persistenceService.createOnlineVersion(ns, name, version, preferredLatest);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"callInterfaces\")) {\n        throw new NacosApiException(NacosException.INVALID_PARAM, \"callInterfaces is required for online Versions\");\n    }\n    throw e;\n}","preventionTips":["Always populate callInterfaces when building an AgentVersionDetail for the online path.","Use a builder or factory method that enforces callInterfaces as a required field.","Run AgentValidationUtils checks and request.validate() before reaching the persistence layer."],"tags":["agent","ai-registry","validation","call-interfaces","online-version"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}