alibaba/nacos · error · IllegalArgumentException

Runtime Endpoint healthy must not be null

Error message

Runtime Endpoint healthy must not be null

What it means

Each runtime Endpoint in a revision projection must have a non-null healthy flag. This guard in revisionBytes runs after EndpointCanonicalizer produces the canonical copy, ensuring the health state is explicit before it is written into the deterministic revision frame.

Source

Thrown at ai/src/main/java/com/alibaba/nacos/ai/service/agent/fingerprint/RuntimeEndpointRevision.java:97

    static byte[] revisionBytes(String namespaceId, String agentName, String protocol,
        List<AgentDiscoveryEndpoint> endpoints) {
        AgentValidationUtils.validateNamespaceId(namespaceId);
        AgentValidationUtils.validateAgentName(agentName);
        AgentValidationUtils.validateProtocol(protocol);
        if (endpoints == null) {
            throw new IllegalArgumentException("Runtime Endpoint projection must not be null");
        }
        if (endpoints.size() > MAX_ENDPOINTS) {
            throw new IllegalArgumentException(
                "Runtime Endpoint projection exceeds " + MAX_ENDPOINTS + " items");
        }
        Map<EndpointNaturalKey, AgentDiscoveryEndpoint> canonicalEndpoints =
            new TreeMap<EndpointNaturalKey, AgentDiscoveryEndpoint>();
        for (AgentDiscoveryEndpoint endpoint : endpoints) {
            Endpoint canonicalEndpoint = EndpointCanonicalizer.canonicalize(endpoint);
            AgentDiscoveryEndpoint canonical = copyEndpoint(canonicalEndpoint);
            if (canonical.getHealthy() == null) {
                throw new IllegalArgumentException("Runtime Endpoint healthy must not be null");
            }
            canonical.setBindings(canonicalBindings(endpoint.getBindings()));
            EndpointNaturalKey key = EndpointNaturalKey.of(namespaceId, agentName, protocol,
                canonical);
            if (canonicalEndpoints.put(key, canonical) != null) {
                throw new IllegalArgumentException("Duplicate Runtime Endpoint: " + key);
            }
        }
        return frame(canonicalEndpoints);
    }
    
    private static byte[] frame(Map<EndpointNaturalKey, AgentDiscoveryEndpoint> endpoints) {
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        try (DataOutputStream output = new DataOutputStream(buffer)) {
            output.writeInt(endpoints.size());
            for (AgentDiscoveryEndpoint endpoint : endpoints.values()) {
                writeUtf8(output, endpoint.getUri());
                writeUtf8(output, endpoint.getTransport());

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Set endpoint.setHealthy(true) or endpoint.setHealthy(false) explicitly on every endpoint before computing the revision.
  2. Ensure the runtime agent registration payload includes the healthy field for each endpoint.
  3. Default healthy to true during adaptor conversion if the source protocol does not provide health.

Example fix

// before
endpoint.setHealthy(null);
endpoints.add(endpoint);
RuntimeEndpointRevision.compute(ns, name, proto, endpoints); // throws

// after
endpoint.setHealthy(true);
endpoints.add(endpoint);
RuntimeEndpointRevision.compute(ns, name, proto, endpoints);
Defensive patterns

Strategy: validation

Validate before calling

for (AgentDiscoveryEndpoint ep : endpoints) {
    if (ep.getHealthy() == null) {
        throw new IllegalArgumentException("Endpoint healthy is null: " + ep.getUri());
    }
}

Type guard

boolean allEndpointsHaveHealth(List<AgentDiscoveryEndpoint> endpoints) {
    return endpoints.stream().allMatch(e -> e.getHealthy() != null);
}

Prevention

When it happens

Trigger: Calling RuntimeEndpointRevision.compute with an endpoints list where at least one AgentDiscoveryEndpoint has getHealthy() == null after canonicalization. This happens when a runtime Agent reports endpoints without setting the healthy field.

Common situations: An SDK or agent runtime omits the healthy field when reporting endpoints. A protocol adaptor maps endpoint data but forgets to set health. JSON deserialization leaves healthy unset because the field was absent in the payload.

Related errors


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