apache/cassandra · error · InvalidRequestException

Table with id does not exist

Error message

Table with id {tableId} does not exist

What it means

ConsensusRequestRouter.getTableMetadata(TableId) resolves a TableId to TableMetadata; when the id is not in the schema it throws InvalidRequestException. Like the name-based variants, this is expected mainly when a DROP TABLE races in-flight routing for a request that carries only the table's id.

Solutions

  1. Re-prepare statements / refresh cluster metadata so the client picks up the new TableId after re-creating a table
  2. Retry with backoff if the drop was intentional; stop sending requests for the dropped table
  3. Check schema agreement and force a schema reload on the routing node
  4. If the table should exist, verify it was not accidentally dropped (audit DDL history)

Example fix

// before
PreparedStatement ps = session.prepare("SELECT * FROM ks.tbl WHERE k = ?"); // cached across a DROP/CREATE cycle
// after
// re-prepare on 'table doesn't exist' style errors, e.g. after a DROP+CREATE
session.getCluster().getMetadata().checkSchemaAgreement();
PreparedStatement ps = session.prepare("SELECT * FROM ks.tbl WHERE k = ?");
Defensive patterns

Strategy: try-catch

Validate before calling

TableMetadata tm = session.getCluster().getMetadata().getTable(tableId);
if (tm == null) throw new IllegalArgumentException("Table with id " + tableId + " does not exist");

Try / catch

try { TableMetadata tmd = router.getTableMetadata(cm, tableId); }
catch (InvalidRequestException e) { /* TableId stale: re-resolve from name, re-prepare statements */ }

Prevention

When it happens

Trigger: Routing calls (metadata, isKeyManagedByAccordForReadAndWrite/Write, tableMetadata, tm) receiving a TableId absent from ClusterMetadata/local schema — a dropped table's id still referenced by in-flight requests or cached routing state.

Common situations: DROP TABLE racing Accord traffic; stale prepared statements / cached TableIds in the driver after a table was recreated (new id); version-skew or schema disagreement between nodes.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/service/consensus/migration/ConsensusRequestRouter.java:208

    {
        TableMetadata metadata = getTableMetadata(cm, tableId);
        // Non-distributed tables always take the Paxos path
        if (metadata == null)
            return pickPaxos();
        return routeAndMaybeMigrate(cm, metadata, key, consistencyLevel, requestTime, timeoutNanos, isForWrite);
    }

    public static TableMetadata getTableMetadata(ClusterMetadata cm, TableId tableId)
    {
        TableMetadata tm = cm.schema.getTableMetadata(tableId);
        if (tm == null)
        {
            // It's a non-distributed table which is fine, but we want to error if it doesn't exist
            // We should never actually reach here unless there is a race with dropping the table
            Keyspaces localKeyspaces = Schema.instance.localKeyspaces();
            TableMetadata tm2 = localKeyspaces.getTableOrViewNullable(tableId);
            if (tm2 == null)
                throw new InvalidRequestException("Table with id " + tableId + " does not exist");
            return null;
        }
        return tm;
    }

    protected ConsensusRoutingDecision routeAndMaybeMigrate(ClusterMetadata cm, @Nonnull TableMetadata tmd, @Nonnull DecoratedKey key, ConsistencyLevel consistencyLevel, Dispatcher.RequestTime requestTime, long timeoutNanos, boolean isForWrite)
    {
        if (!tmd.params.transactionalMigrationFrom.isMigrating())
            return decisionFor(tmd.params.transactionalMode);

        TableMigrationState tms = cm.consensusMigrationState.tableStates.get(tmd.id);
        if (tms == null)
            return decisionFor(tmd.params.transactionalMigrationFrom.from);

        Token token = key.getToken();
        if (tms.migratedRanges.intersects(token))
            return pickMigrated(tms.targetProtocol, IAccordService.NO_HLC);

View on GitHub (pinned to 88fd0f6a0e)