{"record":{"id":"57909428451e6c90","repo":"apache/cassandra","slug":"node-s-is-alive-and-owns-this-id-use-decommissio","errorCode":null,"errorMessage":"Node %s is alive and owns this ID. Use decommission command to remove it from the ring","messagePattern":"Node (.+?) is alive and owns this ID\\. Use decommission command to remove it from the ring","errorType":"exception","errorClass":"java.lang.UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/tcm/sequences/SingleNodeSequences.java","lineNumber":136,"sourceCode":"    }\n\n    /**\n     * Entrypoint to begin node removal process\n     *\n     * @param toRemove id of the node to remove\n     * @param force if set to true, will remove the node even if this would mean there will be not enough nodes\n     *              to satisfy replication factor\n     */\n    static void removeNode(NodeId toRemove, boolean force)\n    {\n        ClusterMetadata metadata = ClusterMetadata.current();\n        if (toRemove.equals(metadata.myNodeId()))\n            throw new UnsupportedOperationException(\"Cannot remove self\");\n        InetAddressAndPort endpoint = metadata.directory.endpoint(toRemove);\n        if (endpoint == null)\n            throw new UnsupportedOperationException(\"Host ID not found.\");\n        if (Gossiper.instance.getLiveMembers().contains(endpoint))\n            throw new UnsupportedOperationException(\"Node \" + endpoint + \" is alive and owns this ID. Use decommission command to remove it from the ring\");\n\n        NodeState removeState = metadata.directory.peerState(toRemove);\n        if (removeState == null)\n            throw new UnsupportedOperationException(\"Node to be removed is not a member of the token ring\");\n        if (removeState == NodeState.LEAVING)\n            logger.warn(\"Node {} is already leaving or being removed, continuing removal anyway\", endpoint);\n\n        if (metadata.inProgressSequences.contains(toRemove))\n            throw new UnsupportedOperationException(\"Can not remove a node that has an in-progress sequence\");\n\n        ReconfigureCMS.maybeReconfigureCMS(metadata, endpoint);\n\n        logger.info(\"starting removenode with {} {}\", metadata.epoch, toRemove);\n        Collection<Token> tokens  = metadata.tokenMap.tokens(toRemove);\n        ClusterMetadataService.instance().commit(new PrepareLeave(toRemove,\n                                                                  force,\n                                                                  ClusterMetadataService.instance().placementProvider(),\n                                                                  LeaveStreams.Kind.REMOVENODE));","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/sequences/SingleNodeSequences.java#L118-L154","documentation":"Duplicate/alternate form of the alive-node guard in removeNode: when the target endpoint appears in Gossiper.instance.getLiveMembers(), removal is blocked with the formatted message naming the endpoint. Live nodes must decommission, not be removed, because removal assumes the node is dead and its data will be re-replicated from other replicas.","triggerScenarios":"`nodetool removenode <hostId>` issued while the target endpoint is broadcasting gossip liveness — same node seen as live due to partial partition or the operator mistaking a node for dead.","commonSituations":"Stale gossip liveness after an abrupt crash (heartbeats not yet expired); asymmetric network failure where removal coordinator still sees the node; operator confusion between removenode and decommission semantics.","solutions":["Wait for gossip to mark the endpoint dead (heartbeats expire) before re-running removenode.","If the node is genuinely running, use `nodetool decommission` on it instead.","Use `nodetool gossipinfo` / `nodetool netstats` to confirm observed liveness from the removal coordinator.","Restart the removal from a different coordinator node that sees the target as dead (if the partition is asymmetric)."],"exampleFix":"// before\nnodetool removenode hostId  // target still gossips live\n// after\n// wait for: nodetool gossipinfo shows DOWN for endpoint\nif (!liveMembers.contains(endpoint)) nodetool.removenode(hostId);","handlingStrategy":"validation","validationCode":"Set<InetAddressAndPort> live = Gossiper.instance.getLiveMembers();\nInetAddressAndPort ep = ClusterMetadata.current().directory.endpoint(NodeId.fromString(hostId));\nif (ep != null && live.contains(ep))\n    throw new IllegalArgumentException(\"Endpoint \" + ep + \" still live; decommission instead\");","typeGuard":null,"tryCatchPattern":"try {\n    storageService.removeNode(hostId);\n} catch (UnsupportedOperationException e) {\n    if (e.getMessage().contains(\"is alive and owns this ID\")) {\n        awaitEndpointDown(ep); // poll gossip until dead, then retry\n        storageService.removeNode(hostId);\n    } else throw e;\n}","preventionTips":["Poll gossip liveness until the endpoint is DOWN before automating removenode.","Remember gossip heartbeats take time to expire after a crash; wait before retrying.","Use decommission for reachable nodes; removenode only for confirmed-dead ones.","Cross-check liveness from multiple coordinators when partitions are suspected."],"tags":["removenode","gossip","liveness","decommission"],"backgroundTag":"invalid-argument-value","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}