apache/cassandra · error · InvalidRequestException
Can't route consensus request to nonexistent CFS %s.%s
Error message
Can't route consensus request to nonexistent CFS %s.%s
What it means
During Paxos-to-Accord consensus migration, the router must resolve the table's ColumnFamilyStore (CFS) instance to route a consensus request. If the CFS cannot be found by table ID at routing time, the table has been dropped or is not yet/ no longer present in this node's local schema, and Cassandra throws this InvalidRequestException rather than route to a nonexistent store.
Source
Thrown at src/java/org/apache/cassandra/service/consensus/migration/ConsensusRequestRouter.java:244
if (tms.migratingRanges.intersects(token))
return pickBasedOnKeyMigrationStatus(cm, tmd, tms, key, consistencyLevel, requestTime, timeoutNanos, isForWrite);
// It's not migrated so infer the protocol from the target
return pickNotMigrated(tms.targetProtocol);
}
/**
* If the key was already migrated then we can pick the target protocol otherwise
* we have to run a repair operation on the key to migrate it.
*/
private static ConsensusRoutingDecision pickBasedOnKeyMigrationStatus(ClusterMetadata cm, TableMetadata tmd, TableMigrationState tms, DecoratedKey key, ConsistencyLevel consistencyLevel, Dispatcher.RequestTime requestTime, long timeoutNanos, boolean isForWrite)
{
checkState(pickPaxos() != ConsensusRoutingDecision.PAXOSV1, "Can't migrate from PaxosV1 to anything");
ColumnFamilyStore cfs = ColumnFamilyStore.getIfExists(tmd.id);
if (cfs == null)
throw new InvalidRequestException("Can't route consensus request to nonexistent CFS %s.%s".format(tmd.keyspace, tmd.name));
// Migration to accord has two phases for each range, in the first phase we can't do key migration because Accord
// can't safely read until the range has had its data repaired so Paxos continues to be used for all reads
// and writes
Token token = key.getToken();
if (tms.targetProtocol == ConsensusMigrationTarget.accord && tms.repairPendingRanges.intersects(token))
return pickPaxos();
// If it is locally replicated we can check our local migration state to see if it was already migrated
EndpointsForToken naturalReplicas = ReplicaLayout.forNonLocalStrategyTokenRead(cm, cfs.keyspace.getMetadata(), token);
boolean isLocallyReplicated = naturalReplicas.lookup(FBUtilities.getBroadcastAddressAndPort()) != null;
if (isLocallyReplicated)
{
ConsensusMigratedAt consensusMigratedAt = getConsensusMigratedAt(tms.tableId, key);
// Check that key migration that was performed satisfies the requirements of the current in flight migration
// for the range
// Be aware that for Accord->Paxos the cache only tells us if the key was repaired locally
// This ends up still being safe because every single Paxos read (in a migrating range) during migration will checkView on GitHub (pinned to 88fd0f6a0e)
Solutions
- Check that the table still exists (system_schema.tables / DESCRIBE) and re-create it if it was dropped unintentionally
- Retry the operation on a different node or after schema agreement is reached (nodetool checkschemaversions)
- Clear stale client state: re-prepare statements against the live table
- If it occurs during rolling restarts, ensure the node has fully completed startup and CFS construction before serving traffic
Example fix
// before: blind retry loop on InvalidRequestException
session.execute(lwtInsert);
// after: guard against dropped table
try {
session.execute(lwtInsert);
} catch (InvalidRequestException e) {
if (schema.tableExists(keyspace, table)) throw e;
// table was dropped; skip or recreate
} Defensive patterns
Strategy: validation
Validate before calling
Row row = session.execute("SELECT table_name FROM system_schema.tables WHERE keyspace_name=? AND table_name=?", ks, table).one();
if (row == null) throw new IllegalStateException("Table " + ks + "." + table + " does not exist"); Try / catch
try { session.execute(lwt); } catch (InvalidRequestException e) { /* table likely dropped; refresh schema metadata and re-check */ session.refreshSchema(); } Prevention
- Check table existence before issuing LWTs after DDL changes
- Wait for schema agreement after CREATE/DROP TABLE before sending traffic
- Avoid racing DROP TABLE with in-flight transactions
When it happens
Trigger: A client sends a serial/consensus (LWT or transactional) read or write to a table whose schema metadata still exists in ClusterMetadata but whose local ColumnFamilyStore lookup (ColumnFamilyStore.getIfExists(tmd.id)) returns null — typically the table was dropped concurrently, or the node's local CFS has not been created/not yet initialized for that table.
Common situations: Race between dropping a table and in-flight LWT/transactional requests hitting it; schema disagreement where one node knows the drop and another still routes; requests arriving during node startup before all CFS instances are constructed; stale prepared statements referencing a dropped table.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- The table '%s' does not exist in the keyspace '%s'.
- The receiver table %s.%s specified by call to function %s ha
- Unknown keyspace/cf pair (%s.%s)
- Unknown CF %s %s
- Unknown keyspace: '" + keyspaceName + "'
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/0620464c04595c3b.
Report an issue: GitHub.