apache/cassandra · error · IllegalArgumentException
New tokens exceed total bounds of current placement ranges
Error message
New tokens exceed total bounds of current placement ranges
What it means
splitRangesForPlacement splits existing placement ranges so new tokens become range boundaries. Before splitting it validates that the proposed tokens fit within the total bounds [min, max] of the current placement ranges; IllegalArgumentException is thrown when any token falls outside those bounds, since no existing range could be split to cover it.
Solutions
- Verify every proposed token lies within the current placement range bounds before calling the API (tokens.get(0) >= min and tokens.last <= max)
- Re-assign tokens using the same partitioner/random token allocator that produced the existing ring
- If the ring is intentionally being extended, first allocate initial ranges covering the new tokens (initialize as a new datacenter/cluster operation) rather than splitting
- Correct the token configuration (initial_token / bootstrap token list) and retry the operation
Example fix
// before
cluster.bootstrap(toBootstrap.stream().map(TokenUtils::getToken).collect(Collectors.toSet()));
// after
SortedSet<Token> sorted = ...;
Token min = placements.first().range().left, max = placements.last().range().right;
if (sorted.first().compareTo(min) < 0 || sorted.last().compareTo(max) > 0)
throw new IllegalArgumentException("token outside current placement bounds");
cluster.bootstrap(sorted); Defensive patterns
Strategy: validation
Validate before calling
Token min = eprs.get(0).range().left, max = eprs.get(eprs.size()-1).range().right;
if (tokens.first().compareTo(min) < 0 || tokens.last().compareTo(max) > 0)
throw new IllegalArgumentException("proposed tokens outside current placement bounds"); Try / catch
try { splitRangesForPlacement(tokens, eprs, epoch); } catch (IllegalArgumentException e) { /* regenerate tokens with the cluster's partitioner */ } Prevention
- Generate new tokens with the same partitioner as the existing ring
- Sanity-check token ordering and bounds before bootstrap/replace operations
- Never hand-edit token lists; use the cluster's token allocator
When it happens
Trigger: Calling the TCM bootstrap/replace/move placement APIs (which route through splitRangesForPlacement) with a token set whose minimum is below the left boundary or whose maximum is above the right boundary of the current canonical placements.
Common situations: Assigning a new token outside the currently allocated token space (e.g. wrong partitioner ring bounds); attempting a multi-token bootstrap where one token was accidentally mistyped; replaying placement deltas against ranges that were never allocated (empty or partial ring).
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Proposed tokens must be superset of existing tokens
- Booting with ClusterMetadata from file:
- Can't revert join from
- Cleaning up orphaned PreInitialize at epoch
- Expected to complete startup sequence, but did not. Can't…
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/f05b2df3f97a6a17.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/tcm/ownership/ReplicaGroups.java:317
{
return new Builder(expectedSize);
}
@VisibleForTesting
public static ReplicaGroups splitRangesForPlacement(List<Token> tokens, ReplicaGroups placement)
{
if (placement.ranges.isEmpty())
return placement;
Builder newPlacement = ReplicaGroups.builder();
List<VersionedEndpoints.ForRange> eprs = new ArrayList<>(placement.endpoints);
eprs.sort(Comparator.comparing(a -> a.range().left));
Token min = eprs.get(0).range().left;
Token max = eprs.get(eprs.size() - 1).range().right;
// if any token is < the start or > the end of the ranges covered, error
if (tokens.get(0).compareTo(min) < 0 || (!max.equals(min) && tokens.get(tokens.size()-1).compareTo(max) > 0))
throw new IllegalArgumentException("New tokens exceed total bounds of current placement ranges " + tokens + " " + eprs);
Iterator<VersionedEndpoints.ForRange> iter = eprs.iterator();
VersionedEndpoints.ForRange current = iter.next();
for (Token token : tokens)
{
// handle special case where one of the tokens is the min value
if (token.equals(min))
continue;
assert current != null : tokens + " " + eprs;
Range<Token> r = current.get().range();
int cmp = token.compareTo(r.right);
if (cmp == 0)
{
newPlacement.withReplicaGroup(current);
if (iter.hasNext())
current = iter.next();
else
current = null;View on GitHub (pinned to 88fd0f6a0e)