apache/cassandra · error · ConfigurationException
Can't add full replicas if there are any transient replicas.
Error message
Can't add full replicas if there are any transient replicas. You must first remove all transient replicas, then change the # of full replicas, then add back the transient replicas
What it means
Transient replication does not support a direct transition from more full replicas with existing transients to fewer full replicas: the transient->full transition lacks the pending state needed for correctness, so a read could hit a transient replica as if it were a full one. The change must be done stepwise.
Source
Thrown at src/java/org/apache/cassandra/cql3/statements/schema/AlterKeyspaceStatement.java:217
if (newTrans > 0)
{
if (DatabaseDescriptor.getNumTokens() > 1)
throw new ConfigurationException(String.format("Transient replication is not supported with vnodes yet"));
if (!current.views.isEmpty())
throw new ConfigurationException("Cannot use transient replication on keyspaces using materialized views");
for (TableMetadata table : current.tables)
if (!table.indexes.isEmpty())
throw new ConfigurationException("Cannot use transient replication on keyspaces using secondary indexes");
}
//This is true right now because the transition from transient -> full lacks the pending state
//necessary for correctness. What would happen if we allowed this is that we would attempt
//to read from a transient replica as if it were a full replica.
if (oldFull > newFull && oldTrans > 0)
throw new ConfigurationException("Can't add full replicas if there are any transient replicas. You must first remove all transient replicas, then change the # of full replicas, then add back the transient replicas");
//Don't increase transient replication factor by more than one at a time if changing number of replicas
//Just like with changing full replicas it's not safe to do this as you could read from too many replicas
//that don't have the necessary data. W/O transient replication this alteration was allowed and it's not clear
//if it should be.
//This is structured so you can convert as many full replicas to transient replicas as you want.
boolean numReplicasChanged = oldTrans + oldFull != newTrans + newFull;
if (numReplicasChanged && (newTrans > oldTrans && newTrans != oldTrans + 1))
throw new ConfigurationException("Can only safely increase number of transients one at a time with incremental repair run in between each time");
}
@Override
public AuditLogContext getAuditLogContext()
{
return new AuditLogContext(AuditLogEntryType.ALTER_KEYSPACE, keyspaceName);
}
public String toString()View on GitHub (pinned to 88fd0f6a0e)
Solutions
- First remove all transient replicas (e.g. '3/1' -> '3/0'), run incremental repair, then change full RF ('3/0' -> '2/0' or target), then re-add transients one at a time with repair between steps.
- Follow the documented multi-step sequence; verify with an incremental repair after each step.
- Avoid mixing full-RF changes and transient-RF changes in a single ALTER KEYSPACE.
Example fix
// before (one step)
"ALTER KEYSPACE ks WITH replication = {'dc1':'3/1'}"; // from '2/1'
// after (staged)
"ALTER KEYSPACE ks WITH replication = {'dc1':'2/0'}"; runIncrementalRepair();
"ALTER KEYSPACE ks WITH replication = {'dc1':'3/0'}"; runIncrementalRepair();
"ALTER KEYSPACE ks WITH replication = {'dc1':'3/1'}"; Defensive patterns
Strategy: validation
Validate before calling
if (oldFull > newFull && oldTrans > 0) throw new IllegalArgumentException("stage the RF change: remove transients first, repair, then change full RF"); Try / catch
try { session.execute(alterKeyspace); } catch (ConfigurationException e) { if (e.getMessage().contains("Can't add full replicas if there are any transient replicas")) applyStagedReplicationChange(current, target); else throw e; } Prevention
- Never combine full-RF and transient-RF changes in one ALTER KEYSPACE
- Script the remove-transients -> repair -> change-full -> re-add-transients sequence
- Run incremental repair between every stage
When it happens
Trigger: `ALTER KEYSPACE ks WITH replication = {'dc1':'2/1' -> '3/1'}` style change where oldFull > newFull and oldTrans > 0 — i.e. adding full replicas while transient replicas still exist.
Common situations: Operators trying to rebalance RF in one step on a transient-replication keyspace, e.g. increasing full RF from 2 to 3 while keeping 1 transient replica.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Transient replication is not supported with vnodes yet
- Cannot use transient replication on keyspaces using material
- Cannot use transient replication on keyspaces using secondar
- Can only safely increase number of transients one at a time
- Cannot alter RF while some endpoints are not in normal state
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/960e32a01bb6c1c9.
Report an issue: GitHub.