{"record":{"id":"8d57825985585458","repo":"apache/cassandra","slug":"can-t-upgrade-the-first-node-when-status","errorCode":null,"errorMessage":"Can't upgrade the first node when STATUS = ","messagePattern":"Can't upgrade the first node when STATUS = ","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/tcm/compatibility/GossipHelper.java","lineNumber":244,"sourceCode":"        {\n            throw new RuntimeException(e);\n        }\n    }\n\n    private static NodeState toNodeState(InetAddressAndPort endpoint, EndpointState epState)\n    {\n        assert epState != null;\n\n        String status = epState.getStatus();\n        if (status.equals(VersionedValue.STATUS_NORMAL) ||\n            status.equals(VersionedValue.SHUTDOWN) ||\n            status.equals(VersionedValue.HIBERNATE))\n            return NodeState.JOINED;\n        if (status.equals(VersionedValue.STATUS_LEFT))\n            return NodeState.LEFT;\n        if (status.isEmpty())\n            return NodeState.REGISTERED;\n        throw new IllegalStateException(\"Can't upgrade the first node when STATUS = \" + status + \" for node \" + endpoint);\n    }\n\n    public static NodeAddresses getAddressesFromEndpointState(InetAddressAndPort endpoint, EndpointState epState)\n    {\n        if (endpoint.equals(getBroadcastAddressAndPort()))\n            return NodeAddresses.current();\n        try\n        {\n            InetAddressAndPort local = getEitherState(endpoint, epState, INTERNAL_ADDRESS_AND_PORT, INTERNAL_IP, DatabaseDescriptor.getStoragePort());\n            InetAddressAndPort nativeAddress = getEitherState(endpoint, epState, NATIVE_ADDRESS_AND_PORT, RPC_ADDRESS, DatabaseDescriptor.getNativeTransportPort());\n            return new NodeAddresses(UUID.randomUUID(), endpoint, local, nativeAddress);\n        }\n        catch (UnknownHostException e)\n        {\n            throw new ConfigurationException(\"Unknown host in epState for \" + endpoint + \" : \" + epState, e);\n        }\n    }\n","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/compatibility/GossipHelper.java#L226-L262","documentation":"GossipHelper.toNodeState maps legacy gossip STATUS application-state values to TCM NodeState values; a STATUS value not in the handled set throws IllegalStateException because the first-node upgrade path cannot classify that endpoint. This is a strictness guard during the gossip-to-TCM migration of the seed/first node.","triggerScenarios":"Upgrading the first node when some endpoint's gossip status is an unrecognized string (empty handled, JOINED/LEFT/HIBERNATE handled, anything else throws), e.g. BOOTSTRAPPING variants or unexpected/legacy values.","commonSituations":"Mixed-version gossip during rolling upgrade; stale gossip state from long-dead nodes; nodes mid-operation (e.g. leaving/moving) at upgrade time; corrupted endpoint state.","solutions":["Ensure the whole cluster is quiesced (no bootstrap/leaving/move in flight) before the TCM upgrade of the first node","Remove dead/stale endpoints from gossip (nodetool removenode / assassinate where appropriate) before upgrading","Upgrade all nodes to the gossip-compat version before starting the migration","If a legit status is unhandled, extend toNodeState with the missing mapping"],"exampleFix":"// before\nif (status.isEmpty())\n    return NodeState.REGISTERED;\nthrow new IllegalStateException(\"Can't upgrade the first node when STATUS = \" + status);\n// after\nif (status.isEmpty())\n    return NodeState.REGISTERED;\nif (status.startsWith(VersionedValue.STATUS_BOOTSTRAPPING))\n    return NodeState.BOOTSTRAPPING;\nthrow new IllegalStateException(\"Can't upgrade the first node when STATUS = \" + status);","handlingStrategy":"validation","validationCode":"String status = getGossipStatus(endpoint);\nSet<String> ok = Set.of(STATUS_NORMAL, STATUS_BOOTSTRAPPING, STATUS_LEAVING, STATUS_LEFT, HIBERNATE, \"\");\nif (!ok.contains(status) && !status.startsWith(\"BOOTSTRAP\"))\n    log.warn(\"Unmapped gossip status {} for {} before upgrade\", status, endpoint);","typeGuard":null,"tryCatchPattern":"try { NodeState ns = GossipHelper.toNodeState(endpoint, epState, tokens); }\ncatch (IllegalStateException e) {\n    if (e.getMessage().startsWith(\"Can't upgrade the first node\")) { /* quiesce cluster, clean gossip, retry */ }\n    else throw e;\n}","preventionTips":["Quiesce all topology operations (bootstrap/leaving/move) before first-node upgrade","Remove stale gossip endpoints beforehand","Upgrade whole cluster to the compat version before migration"],"tags":["gossip","upgrade","tcm","compatibility"],"backgroundTag":"invalid-enum-value","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"}