alibaba/nacos · error · IllegalArgumentException

Duplicate Endpoint source: {source}

Error message

Duplicate Endpoint source: {source}

What it means

Thrown by validateEndpointSourceOrder when the same EndpointSource value appears more than once in the list. Since endpointSourceOrder defines a strict preference sequence, repeating a source (e.g. [DECLARED, DECLARED]) is meaningless and is rejected. Each entry is also null-checked via requireNonNull before this uniqueness test.

Source

Thrown at api/src/main/java/com/alibaba/nacos/api/ai/utils/AgentModelValidator.java:526

        for (AgentCallInterface callInterface : callInterfaces) {
            validateCallInterface(namespaceId, agentName, callInterface);
            if (!protocols.add(callInterface.getProtocol())) {
                throw new IllegalArgumentException(
                    "Duplicate CallInterface protocol: " + callInterface.getProtocol());
            }
        }
    }
    
    private static void validateEndpointSourceOrder(List<EndpointSource> sourceOrder) {
        requireNonNull(sourceOrder, "endpointSourceOrder");
        if (sourceOrder.isEmpty() || sourceOrder.size() > EndpointSource.values().length) {
            throw new IllegalArgumentException("endpointSourceOrder must contain 1 or 2 sources");
        }
        Set<EndpointSource> uniqueSources = new HashSet<EndpointSource>();
        for (EndpointSource source : sourceOrder) {
            requireNonNull(source, "endpointSourceOrder item");
            if (!uniqueSources.add(source)) {
                throw new IllegalArgumentException("Duplicate Endpoint source: " + source);
            }
        }
    }
    
    private static void validateDeclaredEndpoints(String namespaceId, String agentName,
        String protocol, List<Endpoint> endpoints) {
        if (endpoints == null) {
            return;
        }
        if (endpoints.size() > MAX_DECLARED_ENDPOINTS) {
            throw new IllegalArgumentException(
                "declaredEndpoints exceeds " + MAX_DECLARED_ENDPOINTS + " items");
        }
        Set<EndpointNaturalKey> endpointKeys = new HashSet<EndpointNaturalKey>();
        for (Endpoint endpoint : endpoints) {
            validateEndpoint(endpoint);
            EndpointNaturalKey key = EndpointNaturalKey.of(namespaceId, agentName, protocol,
                endpoint);

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. List each EndpointSource at most once in endpointSourceOrder.
  2. Deduplicate the list while preserving the intended first-preference order.
  3. Construct the list explicitly from distinct EndpointSource values.

Example fix

// before
callInterface.setEndpointSourceOrder(List.of(EndpointSource.DECLARED, EndpointSource.DECLARED));
// after
callInterface.setEndpointSourceOrder(List.of(EndpointSource.DECLARED));
Defensive patterns

Strategy: validation

Validate before calling

static List<EndpointSource> dedupSourceOrder(List<EndpointSource> order) {
    return new ArrayList<>(new LinkedHashSet<>(order));
}

Type guard

static boolean sourceOrderIsUnique(List<EndpointSource> order) {
    return order == null || new HashSet<>(order).size() == order.size();
}

Try / catch

try {
    AgentModelValidator.validateCallInterface(ci);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Duplicate Endpoint source")) {
        ci.setEndpointSourceOrder(new ArrayList<>(new LinkedHashSet<>(ci.getEndpointSourceOrder())));
    }
}

Prevention

When it happens

Trigger: endpointSourceOrder = [DISCOVERED, DISCOVERED]; building the list by concatenating a default with an override that repeats the default.

Common situations: Defaulting the list to [DECLARED] then appending DECLARED again from config; copy-paste between interfaces that left a duplicate.

Related errors


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/f7f18f56e68959b3. Report an issue: GitHub.