{"record":{"id":"6bc19d91586bc625","repo":"apache/cassandra","slug":"failed-to-find-endpoints-to-fetch","errorCode":null,"errorMessage":"Failed to find endpoints to fetch ","messagePattern":"Failed to find endpoints to fetch ","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/dht/RangeStreamer.java","lineNumber":553,"sourceCode":"             }\n             else\n             {\n                 //Without strict consistency we have given up on correctness so no point in fetching from\n                 //a random full + transient replica since it's also likely to lose data\n                 //Also apply testSourceFilters that were given to us so we can safely select a single source\n                 sources = sorted.apply(movements.get(params).get(toFetch).filter(and(isSufficient, testSourceFilters)));\n                 //Limit it to just the first possible source, we don't need more than one and downstream\n                 //will fetch from every source we supply\n                 sources = sources.size() > 0 ? sources.subList(0, 1) : sources;\n             }\n\n             // storing range and preferred endpoint set\n             rangesToFetchWithPreferredEndpoints.putAll(toFetch, sources, Conflict.NONE);\n             logger.debug(\"Endpoints to fetch for {} are {}\", toFetch, sources);\n\n             EndpointsForRange addressList = rangesToFetchWithPreferredEndpoints.getIfPresent(toFetch);\n             if (addressList == null)\n                 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\");","sourceCodeStart":535,"sourceCodeEnd":571,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/dht/RangeStreamer.java#L535-L571","documentation":"After RangeStreamer computes sources for a range and puts them into rangesToFetchWithPreferredEndpoints, it immediately reads the entry back with getIfPresent(). A null result means the multimap internally failed to retain the sources for that range — an internal invariant violation (e.g. conflict resolution discarding the entry), so it throws IllegalStateException.","triggerScenarios":"calculateRangesToFetchWithPreferredEndpoints(): rangesToFetchWithPreferredEndpoints.putAll(toFetch, sources, Conflict.NONE) is immediately followed by a null getIfPresent(toFetch) — should be unreachable in normal operation; reachable only via logic bugs or conflicting duplicate range entries resolved to NONE.","commonSituations":"Encountered during streaming bootstrap/rebuild with overlapping range entries conflicting (NONE conflict policy dropping both); typically indicates a bug or unusual topology causing duplicate range submissions.","solutions":["Report/inspect for duplicate range entries causing Conflict.NONE resolution; upgrade to a fixed Cassandra version","Retry the bootstrap/rebuild after restarting the node","Check topology for overlapping tokens (e.g. from an interrupted move) and run a full repair to normalize token metadata"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { fetch(); } catch (IllegalStateException e) { if (e.getMessage().startsWith(\"Failed to find endpoints to fetch\")) { restartNodeAndRetry(); reportBug(e); } else throw e; }","preventionTips":["Keep Cassandra upgraded to current patch versions (this is an internal invariant check)","Avoid interrupted move/decommission states; complete or roll back operations","Run `nodetool repair` after any failed streaming operation"],"tags":["streaming","invariant","internal-state"],"backgroundTag":"internal-invariant-violation","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"}