{"record":{"id":"ec2b2d69bea77de2","repo":"apache/cassandra","slug":"invalid-endpoint-state-for","errorCode":null,"errorMessage":"Invalid endpoint state for {}; {} - {}","messagePattern":"Invalid endpoint state for (.+?); (.+?) - (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/java/org/apache/cassandra/tcm/compatibility/GossipHelper.java","lineNumber":464,"sourceCode":"                                   InProgressSequences.EMPTY,\n                                   ConsensusMigrationState.EMPTY,\n                                   extensions,\n                                   AccordStaleReplicas.EMPTY,\n                                   CMSMembership.EMPTY);\n    }\n\n    public static boolean isValidForClusterMetadata(Map<InetAddressAndPort, EndpointState> epstates)\n    {\n        if (epstates.isEmpty())\n            return false;\n        EnumSet<ApplicationState> requiredStates = EnumSet.of(DC, RACK, HOST_ID, RELEASE_VERSION);\n        for (Map.Entry<InetAddressAndPort, EndpointState> entry : epstates.entrySet())\n        {\n            EndpointState epstate = entry.getValue();\n            for (ApplicationState state : requiredStates)\n                if (epstate.getApplicationState(state) == null)\n                {\n                    logger.warn(\"Invalid endpoint state for {}; {} - {}\", entry.getKey(), state, epstates);\n                    return false;\n                }\n        }\n        return true;\n    }\n\n    private static boolean containsDuplicateHostIds(Map<InetAddressAndPort, EndpointState> epstates)\n    {\n        Set<String> hostIds = new HashSet<>();\n        for (EndpointState epstate : epstates.values())\n        {\n            VersionedValue vv = epstate.getApplicationState(HOST_ID);\n            if (vv == null)\n                continue;\n            String hostIdString = vv.value;\n            if (hostIds.contains(hostIdString))\n                return true;\n            hostIds.add(hostIdString);","sourceCodeStart":446,"sourceCodeEnd":482,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/compatibility/GossipHelper.java#L446-L482","documentation":"GossipHelper.isValidForClusterMetadata checks that every gossip EndpointState carries all ApplicationState values required to build ClusterMetadata. If any required state is missing for a node, it logs a warning naming the endpoint, the missing state, and the full epstates map, and returns false so the gossip-to-TCM upgrade path refuses to proceed.","triggerScenarios":"During upgrade from gossip-based metadata to TCM (GossipHelper.fromEndpointStates path), when a node in the gossip ring has not yet published one of the required ApplicationState entries (e.g. host ID, tokens, or schema version) because it just joined, is partially up, or is running an older version.","commonSituations":"Rolling upgrades where some nodes still run pre-TCM gossip semantics; a node crashed mid-join leaving incomplete endpoint state; racing the upgrade before all nodes published required states.","solutions":["Ensure every node in the ring is running a TCM-capable version and fully joined (check gossip state via nodetool gossipinfo).","Restart or repair the offending node so it republishes its ApplicationState (host ID, tokens, DC/RACK).","Wait for gossip to converge and retry the upgrade/compatibility step.","Remove decommissioned/ghost endpoints that permanently lack required states."],"exampleFix":"// before: proceeding to convert gossip on incomplete state\nif (GossipHelper.isValidForClusterMetadata(epstates)) { convert(); }\n// after: gate on full membership readiness\nif (liveNodes.stream().allMatch(this::hasRequiredStates) && GossipHelper.isValidForClusterMetadata(epstates)) { convert(); }","handlingStrategy":"validation","validationCode":"// Check required gossip states on all endpoints before TCM conversion\nSet<ApplicationState> required = EnumSet.of(ApplicationState.HOST_ID, ApplicationState.TOKENS, ApplicationState.DC);\nboolean ready = epstates.values().stream()\n    .allMatch(es -> required.stream().allMatch(s -> es.getApplicationState(s) != null));","typeGuard":null,"tryCatchPattern":"// Wait for convergence instead of failing fast\nif (!GossipHelper.isValidForClusterMetadata(epstates)) {\n    Uninterruptibles.sleepUninterruptibly(10, TimeUnit.SECONDS);\n    // re-fetch epstates and retry\n}","preventionTips":["Complete rolling upgrades fully before gossip-to-TCM conversion.","Ensure all nodes are UP and fully joined before upgrade steps.","Purge ghost/dead endpoints from gossip."],"tags":["gossip","tcm","upgrade","endpoint-state"],"backgroundTag":"missing-required-config-field","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}