alibaba/nacos · error · IllegalArgumentException

Management or declared Endpoint forbids healthy

Error message

Management or declared Endpoint forbids healthy

What it means

Thrown by validateEndpoint when a declared or management Endpoint has a non-null healthy field. The healthy flag is reserved for runtime snapshots (RuntimeEndpointSnapshotItem carries its own enabled/healthy/state); declared endpoints on an AgentCallInterface are static configuration and must not embed a health opinion, so Endpoint.getHealthy() must be null for them. The check runs after EndpointCanonicalizer.canonicalize, so it inspects the (copied) endpoint value.

Source

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

        RuntimeEndpointState expected;
        if (!item.getEnabled()) {
            expected = RuntimeEndpointState.DISABLED;
        } else if (!item.getHealthy()) {
            expected = RuntimeEndpointState.UNHEALTHY;
        } else {
            expected = RuntimeEndpointState.AVAILABLE;
        }
        if (item.getState() != expected) {
            throw new IllegalArgumentException(
                "Runtime Endpoint state must be " + expected.name());
        }
    }
    
    private static void validateEndpoint(Endpoint endpoint) {
        requireNonNull(endpoint, "Endpoint");
        EndpointCanonicalizer.canonicalize(endpoint);
        if (endpoint.getHealthy() != null) {
            throw new IllegalArgumentException("Management or declared Endpoint forbids healthy");
        }
    }
    
    private static void validateAbsoluteUri(String value, String fieldName) {
        if (value.isEmpty() || codePointLength(value) > MAX_URI_LENGTH) {
            throw new IllegalArgumentException("Invalid " + fieldName + ": " + value);
        }
        try {
            URI uri = new URI(value);
            if (!uri.isAbsolute()) {
                throw new IllegalArgumentException("Invalid " + fieldName + ": " + value);
            }
        } catch (URISyntaxException e) {
            throw new IllegalArgumentException("Invalid " + fieldName + ": " + value, e);
        }
    }
    
    private static void validateRequiredLength(String value, int maximum, String fieldName) {

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Set healthy to null on every Endpoint you put into declaredEndpoints (or simply never set it).
  2. Keep runtime health on RuntimeEndpointSnapshotItem.enabled/healthy/state, never on the Endpoint value used in declared lists.
  3. If you share an Endpoint type between declared and runtime contexts, clear healthy before adding to declaredEndpoints.
  4. Build declared endpoints from a factory that never touches the healthy setter.

Example fix

// before
Endpoint e = new Endpoint();
e.setUri("grpc://svc:8080");
e.setHealthy(true); // forbidden on declared endpoint -> rejected
callInterface.setDeclaredEndpoints(List.of(e));
// after
Endpoint e = new Endpoint();
e.setUri("grpc://svc:8080"); // healthy stays null
callInterface.setDeclaredEndpoints(List.of(e));
Defensive patterns

Strategy: validation

Validate before calling

for (AgentCallInterface ci : agent.getCallInterfaces()) {
    List<Endpoint> eps = ci.getDeclaredEndpoints();
    if (eps == null) continue;
    for (Endpoint e : eps) {
        if (e.getHealthy() != null) {
            throw new IllegalStateException("declared endpoint must not set healthy: " + e.getUri());
        }
    }
}

Type guard

static boolean declaredEndpointsHealthyFree(List<Endpoint> eps) {
    if (eps == null) return true;
    for (Endpoint e : eps) if (e.getHealthy() != null) return false;
    return true;
}

Try / catch

try {
    AgentModelValidator.validateAgent(agent);
} catch (IllegalArgumentException e) {
    if (e.getMessage().equals("Management or declared Endpoint forbids healthy")) {
        // null out healthy on each declared endpoint and retry
    } else throw e;
}

Prevention

When it happens

Trigger: Any declared endpoint list (AgentCallInterface.getDeclaredEndpoints()) or management endpoint that includes a non-null healthy value, submitted through Agent publish/update via validateAgent. validateEndpoint is also used for runtime items' Endpoint but there healthy is set on the item, not the Endpoint — so this specifically catches healthy being wrongly placed on the Endpoint value.

Common situations: Reusing a runtime snapshot Endpoint object (which had healthy set) as a declared endpoint; a shared DTO that defaults healthy=true; copy-pasting from a health-bearing model into the declared-endpoint model; an ORM/serializer that materializes healthy from a default.

Related errors


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