{"record":{"id":"ed12c5bdd4d831b4","repo":"alibaba/nacos","slug":"management-or-declared-endpoint-forbids-healthy","errorCode":null,"errorMessage":"Management or declared Endpoint forbids healthy","messagePattern":"Management or declared Endpoint forbids healthy","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/com/alibaba/nacos/api/ai/utils/AgentModelValidator.java","lineNumber":619,"sourceCode":"        RuntimeEndpointState expected;\n        if (!item.getEnabled()) {\n            expected = RuntimeEndpointState.DISABLED;\n        } else if (!item.getHealthy()) {\n            expected = RuntimeEndpointState.UNHEALTHY;\n        } else {\n            expected = RuntimeEndpointState.AVAILABLE;\n        }\n        if (item.getState() != expected) {\n            throw new IllegalArgumentException(\n                \"Runtime Endpoint state must be \" + expected.name());\n        }\n    }\n    \n    private static void validateEndpoint(Endpoint endpoint) {\n        requireNonNull(endpoint, \"Endpoint\");\n        EndpointCanonicalizer.canonicalize(endpoint);\n        if (endpoint.getHealthy() != null) {\n            throw new IllegalArgumentException(\"Management or declared Endpoint forbids healthy\");\n        }\n    }\n    \n    private static void validateAbsoluteUri(String value, String fieldName) {\n        if (value.isEmpty() || codePointLength(value) > MAX_URI_LENGTH) {\n            throw new IllegalArgumentException(\"Invalid \" + fieldName + \": \" + value);\n        }\n        try {\n            URI uri = new URI(value);\n            if (!uri.isAbsolute()) {\n                throw new IllegalArgumentException(\"Invalid \" + fieldName + \": \" + value);\n            }\n        } catch (URISyntaxException e) {\n            throw new IllegalArgumentException(\"Invalid \" + fieldName + \": \" + value, e);\n        }\n    }\n    \n    private static void validateRequiredLength(String value, int maximum, String fieldName) {","sourceCodeStart":601,"sourceCodeEnd":637,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/api/src/main/java/com/alibaba/nacos/api/ai/utils/AgentModelValidator.java#L601-L637","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set healthy to null on every Endpoint you put into declaredEndpoints (or simply never set it).","Keep runtime health on RuntimeEndpointSnapshotItem.enabled/healthy/state, never on the Endpoint value used in declared lists.","If you share an Endpoint type between declared and runtime contexts, clear healthy before adding to declaredEndpoints.","Build declared endpoints from a factory that never touches the healthy setter."],"exampleFix":"// before\nEndpoint e = new Endpoint();\ne.setUri(\"grpc://svc:8080\");\ne.setHealthy(true); // forbidden on declared endpoint -> rejected\ncallInterface.setDeclaredEndpoints(List.of(e));\n// after\nEndpoint e = new Endpoint();\ne.setUri(\"grpc://svc:8080\"); // healthy stays null\ncallInterface.setDeclaredEndpoints(List.of(e));","handlingStrategy":"validation","validationCode":"for (AgentCallInterface ci : agent.getCallInterfaces()) {\n    List<Endpoint> eps = ci.getDeclaredEndpoints();\n    if (eps == null) continue;\n    for (Endpoint e : eps) {\n        if (e.getHealthy() != null) {\n            throw new IllegalStateException(\"declared endpoint must not set healthy: \" + e.getUri());\n        }\n    }\n}","typeGuard":"static boolean declaredEndpointsHealthyFree(List<Endpoint> eps) {\n    if (eps == null) return true;\n    for (Endpoint e : eps) if (e.getHealthy() != null) return false;\n    return true;\n}","tryCatchPattern":"try {\n    AgentModelValidator.validateAgent(agent);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().equals(\"Management or declared Endpoint forbids healthy\")) {\n        // null out healthy on each declared endpoint and retry\n    } else throw e;\n}","preventionTips":["Never call setHealthy on an Endpoint used in declaredEndpoints.","Keep runtime health on RuntimeEndpointSnapshotItem.enabled/healthy/state.","If reusing Endpoint objects across contexts, clear healthy before adding to declared lists."],"tags":["ai-agent","validation","endpoints","field-reserved"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}