{"record":{"id":"a61662f990649bd4","repo":"apache/cassandra","slug":"cannot-replace-node-s-which-is-not-currently-join","errorCode":null,"errorMessage":"Cannot replace node %s which is not currently joined","messagePattern":"Cannot replace node (.+?) which is not currently joined","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/service/StorageService.java","lineNumber":818,"sourceCode":"            }\n            else\n            {\n                throw new ConfigurationException(\"This node was decommissioned and will not rejoin the ring unless cassandra.override_decommission=true has been set, or all existing data is removed and the node is bootstrapped again\");\n            }\n        }\n\n        if (DatabaseDescriptor.getReplaceTokens().size() > 0 || DatabaseDescriptor.getReplaceNode() != null)\n            throw new RuntimeException(\"Replace method removed; use cassandra.replace_address instead\");\n\n        if (isReplacing())\n        {\n            if (SystemKeyspace.bootstrapComplete())\n                throw new RuntimeException(\"Cannot replace with a node that is already bootstrapped\");\n\n            InetAddressAndPort replaceAddress = DatabaseDescriptor.getReplaceAddress();\n            Directory directory = ClusterMetadata.current().directory;\n            if (directory.peerId(replaceAddress) == null || directory.peerState(replaceAddress) != JOINED)\n                throw new RuntimeException(String.format(\"Cannot replace node %s which is not currently joined\", replaceAddress));\n\n            BootstrapAndReplace.checkUnsafeReplace(shouldBootstrap());\n        }\n\n        if (isReplacingSameAddress())\n        {\n            BootstrapAndReplace.gossipStateToHibernate(ClusterMetadata.current(), ClusterMetadata.currentNullable().myNodeId());\n            Gossiper.instance.start(SystemKeyspace.incrementAndGetGeneration(), false);\n        }\n        else\n        {\n            Gossiper.instance.start(SystemKeyspace.incrementAndGetGeneration(),\n                                    ClusterMetadataService.state() != ClusterMetadataService.State.GOSSIP); // only populate local state if not running in gossip mode\n        }\n\n        Gossiper.instance.register(this);\n        Gossiper.instance.addLocalApplicationState(ApplicationState.NET_VERSION, valueFactory.networkVersion());\n        Gossiper.instance.addLocalApplicationState(ApplicationState.SSTABLE_VERSIONS,","sourceCodeStart":800,"sourceCodeEnd":836,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/service/StorageService.java#L800-L836","documentation":"In replace mode, the node named by cassandra.replace_address must exist in the cluster directory with peer state JOINED. If the address is unknown to the cluster or the peer is not in JOINED state, the replacement cannot take over its token range and a RuntimeException naming the address is thrown.","triggerScenarios":"initServer with cassandra.replace_address pointing at an IP never part of the cluster, a node that was decommissioned/removed, or a node still joining (not JOINED).","commonSituations":"Typo in cassandra.replace_address; replacing a node that was already removed via removenode/decommission; trying to replace during the target's own bootstrap; stale replace address after ring changes.","solutions":["Verify the target address/host ID matches a live, UP, JOINED node (nodetool status)","Remove the dead node properly (nodetool removenode) and bootstrap a new node instead of replacing","Correct cassandra.replace_address to the actual down node's IP","Wait until the target node shows JOINED state before attempting replace"],"exampleFix":"// before\n-Dcassandra.replace_address=10.0.0.99  # never joined\n// after\n-Dcassandra.replace_address=10.0.0.5  # verified down+JOINED in nodetool status","handlingStrategy":"validation","validationCode":"// before replacing: confirm target is a known JOINED peer\nRow r = exec(\"SELECT peer FROM system.peers\"); assert targetInNodetoolStatusAndJoined(replaceAddress);","typeGuard":null,"tryCatchPattern":"try { startNode(); } catch (RuntimeException e) { if (e.getMessage().startsWith(\"Cannot replace node\")) { /* verify address / ring state */ } }","preventionTips":["Confirm the dead node with nodetool status before setting replace_address","Never replace nodes already removed from the ring","Copy the exact IP from nodetool status, not from memory"],"tags":["replace","cluster-membership","configuration"],"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"}