{"record":{"id":"f2fa6c9b8fcab6bd","repo":"apache/cassandra","slug":"unable-to-find-sufficient-sources-for-streaming-ra-f2fa6c","errorCode":null,"errorMessage":"Unable to find sufficient sources for streaming range {} in keyspace {} with RF=1. Keyspace might be missing data.","messagePattern":"Unable to find sufficient sources for streaming range (.+?) in keyspace (.+?) with RF=1\\. Keyspace might be missing data\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/dht/RangeStreamer.java","lineNumber":576,"sourceCode":"              * 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\n    /**\n     * The preferred endpoint list is the wrong format because it is keyed by Replica (this node) rather than the source\n     * endpoint we will fetch from which streaming wants.\n     */\n    public static Multimap<InetAddressAndPort, FetchReplica> convertPreferredEndpointsToWorkMap(EndpointsByReplica preferredEndpoints)","sourceCodeStart":558,"sourceCodeEnd":594,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/dht/RangeStreamer.java#L558-L594","documentation":"Same code path as the strict case in RangeStreamer.calculateRangesToFetchWithPreferredEndpoints, but for RF=1 keyspaces without strict consistency: instead of failing, it logs 'Unable to find sufficient sources for streaming range {range} in keyspace {ks} with RF=1. Keyspace might be missing data.' and continues, leaving that range unfetched. The bootstrapped node will simply lack data for that range.","triggerScenarios":"Bootstrap/range fetch where the single replica of an RF=1 keyspace range is dead or filtered out as a source, and useStrictConsistency is false; the range is skipped with this warning.","commonSituations":"Bootstrapping replacement nodes in clusters with legacy RF=1 keyspaces; a dead sole replica during topology expansion; operators unaware RF=1 keyspaces exist until a node joins/leaves.","solutions":["Identify RF=1 keyspaces (SELECT keyspace_name FROM system_schema.keyspaces / DESC KEYSPACES) and raise RF to >= 2-3, then repair.","Restore the down replica from backup before completing the topology operation.","Rebuild the new node or run a repair/re-stream for the affected keyspace once the replica is back.","Accept and document the data gap if the keyspace is disposable; drop it to silence the warning."],"exampleFix":"// find and fix RF=1 keyspaces\ncqlsh> ALTER KEYSPACE legacy_ks WITH replication = {'class':'NetworkTopologyStrategy','dc1':3};\n$ nodetool repair -full legacy_ks\n$ nodetool cleanup","handlingStrategy":"retry","validationCode":"// detect RF=1 keyspaces before topology operations\nsession.execute(\"SELECT keyspace_name FROM system_schema.keyspaces\").all().stream()\n    .filter(r -> rfOf(r) == 1)\n    .forEach(r -> log.warn(\"RF=1 keyspace {} risks missing data during streaming\", r));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Audit keyspaces for RF=1 before any node join/leave.","After the warning, run repair/rebuild for the affected keyspace once its replica returns.","Keep verified backups of single-replica keyspaces."],"tags":["streaming","bootstrap","replication-factor","data-loss","node-down"],"backgroundTag":"empty-result-set","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"}