{"record":{"id":"e4320d2163b1e252","repo":"alibaba/nacos","slug":"endpointsourceorder-must-contain-1-or-2-sources","errorCode":null,"errorMessage":"endpointSourceOrder must contain 1 or 2 sources","messagePattern":"endpointSourceOrder must contain 1 or 2 sources","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/com/alibaba/nacos/api/ai/utils/AgentModelValidator.java","lineNumber":520,"sourceCode":"        requireNonNull(callInterfaces, \"callInterfaces\");\n        if (callInterfaces.isEmpty() || callInterfaces.size() > MAX_CALL_INTERFACES) {\n            throw new IllegalArgumentException(\n                \"callInterfaces must contain 1 to \" + MAX_CALL_INTERFACES + \" items\");\n        }\n        Set<String> protocols = new HashSet<String>();\n        for (AgentCallInterface callInterface : callInterfaces) {\n            validateCallInterface(namespaceId, agentName, callInterface);\n            if (!protocols.add(callInterface.getProtocol())) {\n                throw new IllegalArgumentException(\n                    \"Duplicate CallInterface protocol: \" + callInterface.getProtocol());\n            }\n        }\n    }\n    \n    private static void validateEndpointSourceOrder(List<EndpointSource> sourceOrder) {\n        requireNonNull(sourceOrder, \"endpointSourceOrder\");\n        if (sourceOrder.isEmpty() || sourceOrder.size() > EndpointSource.values().length) {\n            throw new IllegalArgumentException(\"endpointSourceOrder must contain 1 or 2 sources\");\n        }\n        Set<EndpointSource> uniqueSources = new HashSet<EndpointSource>();\n        for (EndpointSource source : sourceOrder) {\n            requireNonNull(source, \"endpointSourceOrder item\");\n            if (!uniqueSources.add(source)) {\n                throw new IllegalArgumentException(\"Duplicate Endpoint source: \" + source);\n            }\n        }\n    }\n    \n    private static void validateDeclaredEndpoints(String namespaceId, String agentName,\n        String protocol, List<Endpoint> endpoints) {\n        if (endpoints == null) {\n            return;\n        }\n        if (endpoints.size() > MAX_DECLARED_ENDPOINTS) {\n            throw new IllegalArgumentException(\n                \"declaredEndpoints exceeds \" + MAX_DECLARED_ENDPOINTS + \" items\");","sourceCodeStart":502,"sourceCodeEnd":538,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/api/src/main/java/com/alibaba/nacos/api/ai/utils/AgentModelValidator.java#L502-L538","documentation":"Thrown by validateEndpointSourceOrder when a CallInterface's endpointSourceOrder list is empty or has more than EndpointSource.values().length (2) entries. Each CallInterface must declare a non-empty source preference of at most the two available EndpointSource values, defining the order in which declared and discovered endpoints are tried.","triggerScenarios":"A CallInterface with endpointSourceOrder = [] (no endpoint resolution strategy); a list with 3+ entries. Leaving the field unset so it defaults to an empty list.","commonSituations":"Building a CallInterface programmatically and forgetting to set endpointSourceOrder; assuming a server-side default exists (there is none — it is required).","solutions":["Set endpointSourceOrder to a non-empty list of 1 or 2 EndpointSource values.","For a purely declared-endpoint interface, use List.of(EndpointSource.DECLARED); to prefer discovered then declared, use List.of(DISCOVERED, DECLARED).","Never submit a CallInterface with an empty or null endpointSourceOrder."],"exampleFix":"// before\ncallInterface.setEndpointSourceOrder(List.of());\n// after\nimport com.alibaba.nacos.api.ai.model.agent.EndpointSource;\ncallInterface.setEndpointSourceOrder(List.of(EndpointSource.DECLARED));","handlingStrategy":"validation","validationCode":"static List<EndpointSource> checkSourceOrder(List<EndpointSource> order) {\n    if (order == null || order.isEmpty() || order.size() > EndpointSource.values().length) {\n        throw new IllegalArgumentException(\"endpointSourceOrder must contain 1 or 2 sources\");\n    }\n    return order;\n}","typeGuard":"static boolean sourceOrderValid(List<EndpointSource> order) {\n    return order != null && !order.isEmpty() && order.size() <= EndpointSource.values().length;\n}","tryCatchPattern":"try {\n    AgentModelValidator.validateCallInterface(ci);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"endpointSourceOrder must contain\")) {\n        ci.setEndpointSourceOrder(List.of(EndpointSource.DECLARED));\n    }\n}","preventionTips":["Always set endpointSourceOrder explicitly; never rely on a null default.","Use 1 source for single-strategy interfaces, 2 for fallback ordering.","Validate at CallInterface construction time, not only at Agent validation."],"tags":["ai-agent","validation","endpoint","call-interface","illegal-argument"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}