{"record":{"id":"335ee5707299a5e1","repo":"apache/cassandra","slug":"a-node-required-to-move-the-data-consistently-is-d","errorCode":null,"errorMessage":"A node required to move the data consistently is down","messagePattern":"A node required to move the data consistently is down","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/dht/RangeStreamer.java","lineNumber":571,"sourceCode":"                 throw new IllegalStateException(\"Failed to find endpoints to fetch \" + toFetch);\n\n             /*\n              * When we move forwards (shrink our bucket) we are the one losing a range and no one else loses\n              * from that action (we also don't gain). When we move backwards there are two people losing a range. One is a full replica\n              * and the other is a transient replica. So we must need fetch from two places in that case for the full range we gain.\n              * For a transient range we only need to fetch from one.\n              */\n             if (useStrictConsistency && addressList.size() > 1 && (addressList.filter(Replica::isFull).size() > 1 || addressList.filter(Replica::isTransient).size() > 1))\n                 throw new IllegalStateException(String.format(\"Multiple strict sources found for %s, sources: %s\", toFetch, addressList));\n\n             //We must have enough stuff to fetch from\n             if (!any(addressList, isSufficient))\n             {\n                 if (strat.getReplicationFactor().allReplicas == 1)\n                 {\n                     if (useStrictConsistency)\n                     {\n                         logger.warn(\"A node required to move the data consistently is down\");\n                         throw new IllegalStateException(\"Unable to find sufficient sources for streaming range \" + toFetch + \" in keyspace \" + keyspace + \" with RF=1. \" +\n                                                         \"Ensure this keyspace contains replicas in the source datacenter.\");\n                     }\n                     else\n                         logger.warn(\"Unable to find sufficient sources for streaming range {} in keyspace {} with RF=1. \" +\n                                     \"Keyspace might be missing data.\", toFetch, keyspace);\n                 }\n                 else\n                 {\n                     if (useStrictConsistency)\n                         logger.warn(\"A node required to move the data consistently is down\");\n                     throw new IllegalStateException(\"Unable to find sufficient sources for streaming range \" + toFetch + \" in keyspace \" + keyspace);\n                 }\n             }\n         }\n         return rangesToFetchWithPreferredEndpoints.build();\n     }\n","sourceCodeStart":553,"sourceCodeEnd":589,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/dht/RangeStreamer.java#L553-L589","documentation":"In RangeStreamer.calculateRangesToFetchWithPreferredEndpoints, when no live source satisfies the required endpoints for a range in an RF=1 keyspace and strict consistency is requested, the code logs 'A node required to move the data consistently is down' and throws IllegalStateException: strict consistency demands the (single) replica be available to stream, and it is not.","triggerScenarios":"nodetool bootstrap/move/decommission (fetchMap path) with -Dcassandra.consistent.rangemovement=true (strict) where the only replica of an RF=1 keyspace range is dead or not a valid streaming source.","commonSituations":"Bootstrap of a new node while the sole replica of a single-RF keyspace is down; RF=1 keyspaces left over from tests; hardware loss of the only replica combined with consistent range movement requirements.","solutions":["Bring the down node required for streaming back up, then retry the bootstrap/operation.","Temporarily raise the keyspace's replication factor and run repair so more sources exist.","If data loss is acceptable for that keyspace, drop the RF=1 keyspace or proceed without strict consistency (disable consistent range movement) knowingly.","Use a verified backup/snapshot to restore the missing replica before streaming."],"exampleFix":"// ensure enough replicas before topology ops\ncqlsh> ALTER KEYSPACE my_ks WITH replication = {'class':'NetworkTopologyStrategy','dc1':3};\n$ nodetool repair -full my_ks","handlingStrategy":"validation","validationCode":"// preflight: ensure all nodes are up and no RF=1 keyspaces exist before bootstrap\nboolean nodesUp = session.execute(\"SELECT peer FROM system.peers\").all()\n    .stream().allMatch(r -> true); // combine with nodetool status\nboolean hasRf1 = session.execute(\"SELECT keyspace_name, replication FROM system_schema.keyspaces\").all()\n    .stream().anyMatch(r -> r.getMap(\"replication\", String.class, String.class).values().stream()\n        .anyMatch(v -> v.equals(\"1\")));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never run RF=1 keyspaces in production clusters you plan to resize.","Bring all nodes UP before bootstrap/decommission with consistent range movement.","Raise RF and repair before topology changes."],"tags":["streaming","bootstrap","replication-factor","strict-consistency","node-down"],"backgroundTag":"insufficient-permissions","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"}