apache/cassandra · error · IllegalStateException

Failed to find endpoints to fetch

Error message

Failed to find endpoints to fetch 

What it means

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.

Solutions

  1. Report/inspect for duplicate range entries causing Conflict.NONE resolution; upgrade to a fixed Cassandra version
  2. Retry the bootstrap/rebuild after restarting the node
  3. Check topology for overlapping tokens (e.g. from an interrupted move) and run a full repair to normalize token metadata
Defensive patterns

Strategy: try-catch

Try / catch

try { fetch(); } catch (IllegalStateException e) { if (e.getMessage().startsWith("Failed to find endpoints to fetch")) { restartNodeAndRetry(); reportBug(e); } else throw e; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/6bc19d91586bc625. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/dht/RangeStreamer.java:553

             }
             else
             {
                 //Without strict consistency we have given up on correctness so no point in fetching from
                 //a random full + transient replica since it's also likely to lose data
                 //Also apply testSourceFilters that were given to us so we can safely select a single source
                 sources = sorted.apply(movements.get(params).get(toFetch).filter(and(isSufficient, testSourceFilters)));
                 //Limit it to just the first possible source, we don't need more than one and downstream
                 //will fetch from every source we supply
                 sources = sources.size() > 0 ? sources.subList(0, 1) : sources;
             }

             // storing range and preferred endpoint set
             rangesToFetchWithPreferredEndpoints.putAll(toFetch, sources, Conflict.NONE);
             logger.debug("Endpoints to fetch for {} are {}", toFetch, sources);

             EndpointsForRange addressList = rangesToFetchWithPreferredEndpoints.getIfPresent(toFetch);
             if (addressList == null)
                 throw new IllegalStateException("Failed to find endpoints to fetch " + toFetch);

             /*
              * When we move forwards (shrink our bucket) we are the one losing a range and no one else loses
              * from that action (we also don't gain). When we move backwards there are two people losing a range. One is a full replica
              * and the other is a transient replica. So we must need fetch from two places in that case for the full range we gain.
              * For a transient range we only need to fetch from one.
              */
             if (useStrictConsistency && addressList.size() > 1 && (addressList.filter(Replica::isFull).size() > 1 || addressList.filter(Replica::isTransient).size() > 1))
                 throw new IllegalStateException(String.format("Multiple strict sources found for %s, sources: %s", toFetch, addressList));

             //We must have enough stuff to fetch from
             if (!any(addressList, isSufficient))
             {
                 if (strat.getReplicationFactor().allReplicas == 1)
                 {
                     if (useStrictConsistency)
                     {
                         logger.warn("A node required to move the data consistently is down");

View on GitHub (pinned to 88fd0f6a0e)