apache/cassandra · error · IllegalArgumentException

Amount of transient nodes should be strictly positive, but…

Error message

Amount of transient nodes should be strictly positive, but was: '%d'

What it means

When parsing a replication factor string with a transient component, the transient RF count must be strictly positive (the '/0' case is rejected) and never negative. ReplicationFactor.validate throws this IllegalArgumentException if the transient portion is negative, indicating malformed replication syntax.

Solutions

  1. Fix the replication string so the transient count is a positive integer, e.g. 'dc1':'5/1'
  2. Validate that transient replicas < full replicas before submitting the schema change
  3. Re-run the CREATE/ALTER KEYSPACE with the corrected value

Example fix

// before
CREATE KEYSPACE ks WITH replication = {'class':'NetworkTopologyStrategy','dc1':'5/-1'};
// after
CREATE KEYSPACE ks WITH replication = {'class':'NetworkTopologyStrategy','dc1':'5/1'};
Defensive patterns

Strategy: validation

Validate before calling

static ReplicationFactor parseRf(String s) {
    String[] parts = s.split("/");
    int full = Integer.parseInt(parts[0]);
    int transientRf = parts.length > 1 ? Integer.parseInt(parts[1]) : 0;
    if (transientRf < 0) throw new IllegalArgumentException("transient RF must be > 0: " + s);
    if (transientRf >= full) throw new IllegalArgumentException("transient RF must be < full RF: " + s);
    return ReplicationFactor.fromString(s);
}

Try / catch

try { session.execute(createKeyspaceCql); }
catch (InvalidQueryException e) { if (e.getMessage().contains("transient")) { /* correct the RF string and retry */ } }

Prevention

When it happens

Trigger: Defining replication with a negative transient count, e.g. 'dc1':'3/-1', or programmatic construction of a ReplicationFactor with transientRF < 0 (note: transientRF == 0 is also rejected when a '/' separator was present).

Common situations: Typo in the RF string in CREATE KEYSPACE; scripted generation of replication options with unvalidated/interpolated numbers; misconfigured tooling emitting 'n/-m'.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/locator/ReplicationFactor.java:83

                                    "Transient replication is not enabled on this node");
        Preconditions.checkArgument(totalRF >= 0,
                                    "Replication factor must be non-negative, found %s", totalRF);
        Preconditions.checkArgument(transientRF == 0 || transientRF < totalRF,
                                    "Transient replicas must be zero, or less than total replication factor. For %s/%s", totalRF, transientRF);
        if (transientRF > 0)
        {
            Preconditions.checkArgument(DatabaseDescriptor.getNumTokens() == 1,
                                        "Transient nodes are not allowed with multiple tokens");
            Stream<InetAddressAndPort> endpoints = Stream.concat(Gossiper.instance.getLiveMembers().stream(), Gossiper.instance.getUnreachableMembers().stream());
            List<InetAddressAndPort> badVersionEndpoints = endpoints.filter(Predicates.not(FBUtilities.getBroadcastAddressAndPort()::equals))
                                                                    .filter(endpoint -> Gossiper.instance.getReleaseVersion(endpoint) != null && Gossiper.instance.getReleaseVersion(endpoint).major < 4)
                                                                    .collect(Collectors.toList());
            if (!badVersionEndpoints.isEmpty())
                throw new IllegalArgumentException("Transient replication is not supported in mixed version clusters with nodes < 4.0. Bad nodes: " + badVersionEndpoints);
        }
        else if (transientRF < 0)
        {
            throw new IllegalArgumentException(String.format("Amount of transient nodes should be strictly positive, but was: '%d'", transientRF));
        }
    }

    public boolean equals(Object o)
    {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ReplicationFactor that = (ReplicationFactor) o;
        return allReplicas == that.allReplicas && fullReplicas == that.fullReplicas;
    }

    public int hashCode()
    {
        return Objects.hash(allReplicas, fullReplicas);
    }

    public static ReplicationFactor fullOnly(int totalReplicas)
    {

View on GitHub (pinned to 88fd0f6a0e)