alibaba/nacos · error · IllegalArgumentException

Duplicate CallInterface protocol: {callInterface.getProtocol

Error message

Duplicate CallInterface protocol: {callInterface.getProtocol()}

What it means

Thrown by validate when two callInterfaces in the same AgentVersionContent share the same protocol value. Protocols must be unique within a version because each protocol maps to exactly one call interface binding.

Source

Thrown at ai/src/main/java/com/alibaba/nacos/ai/service/agent/storage/AgentVersionContentSerializer.java:166

                + AgentVersionContent.KIND);
        }
        if (!Integer.valueOf(AgentVersionContent.SCHEMA_VERSION)
            .equals(content.getSchemaVersion())) {
            throw new IllegalArgumentException("AgentVersionContent schemaVersion must be "
                + AgentVersionContent.SCHEMA_VERSION);
        }
        List<AgentCallInterface> callInterfaces = content.getCallInterfaces();
        if (callInterfaces == null || callInterfaces.isEmpty()
            || callInterfaces.size() > MAX_CALL_INTERFACES) {
            throw new IllegalArgumentException(
                "AgentVersionContent callInterfaces must contain 1 to " + MAX_CALL_INTERFACES
                    + " items");
        }
        Set<String> protocols = new HashSet<String>();
        for (AgentCallInterface callInterface : callInterfaces) {
            AgentModelValidator.validateCallInterface(callInterface);
            if (!protocols.add(callInterface.getProtocol())) {
                throw new IllegalArgumentException(
                    "Duplicate CallInterface protocol: " + callInterface.getProtocol());
            }
        }
    }
    
    private static Map<String, Object> toStorageProjection(AgentVersionContent content) {
        Map<String, Object> result = new LinkedHashMap<String, Object>();
        result.put("kind", AgentVersionContent.KIND);
        result.put("schemaVersion", AgentVersionContent.SCHEMA_VERSION);
        List<Map<String, Object>> callInterfaces = new ArrayList<Map<String, Object>>();
        for (AgentCallInterface callInterface : content.getCallInterfaces()) {
            callInterfaces.add(toStorageProjection(callInterface));
        }
        result.put("callInterfaces", callInterfaces);
        return result;
    }
    
    private static Map<String, Object> toStorageProjection(AgentCallInterface callInterface) {

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Dedupe callInterfaces by protocol before serializing — keep one entry per protocol.
  2. If you need multiple bindings for one protocol, merge them into a single AgentCallInterface or reconsider the model.

Example fix

// before
List<AgentCallInterface> ifaces = List.of(a2aV1, a2aV2); // both protocol="a2a"

// after
List<AgentCallInterface> ifaces = List.of(a2aV1); // one per protocol
Defensive patterns

Strategy: validation

Validate before calling

Set<String> seen = new HashSet<>();
for (AgentCallInterface ci : callInterfaces) {
    if (!seen.add(ci.getProtocol())) {
        throw new IllegalArgumentException("duplicate protocol: " + ci.getProtocol());
    }
}

Prevention

When it happens

Trigger: Serializing/deserializing content where two AgentCallInterface entries have identical getProtocol(). The HashSet.add returns false on the duplicate, triggering the error with the offending protocol name.

Common situations: A publisher registers two interfaces for the same protocol (e.g. two 'a2a' or two 'mcp' entries) by mistake, or a copy-paste error when building the list.

Related errors


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