apache/cassandra · error · InvalidRequestException

Accord transaction uses dropped tables

Error message

Accord transaction uses dropped tables

What it means

Thrown from AccordResult.tryFailure() when an Accord (transactional) transaction fails and the transaction references tables that have been dropped. The exception is raised instead of the original failure so callers cannot silently proceed against a nonexistent table, mirroring the local bookkeeping markTopologyMismatch.

Source

Thrown at src/java/org/apache/cassandra/service/accord/AccordResult.java:193

            if (txnId != null && txnId.isSyncPoint())
                AccordAgent.onFailedBarrier(txnId, fail);
        }
        else if (isTxnRequest && fail instanceof TopologyMismatch)
        {
            // Excluding bugs topology mismatch can occur because a table was dropped in between creating the txn
            // and executing it.
            // It could also race with the table stopping/starting being managed by Accord.
            // The caller can retry if the table indeed exists and is managed by Accord.
            Set<TableId> txnDroppedTables = txnDroppedTables(keysOrRanges);
            Tracing.trace("Accord returned topology mismatch: " + fail.getMessage());
            logger.debug("Accord returned topology mismatch", fail);
            bookkeeping.markTopologyMismatch();
            // Throw IRE in case the caller fails to check if the table still exists
            if (!txnDroppedTables.isEmpty())
            {
                Tracing.trace("Accord txn uses dropped tables {}", txnDroppedTables);
                logger.debug("Accord txn uses dropped tables {}", txnDroppedTables);
                throw new InvalidRequestException("Accord transaction uses dropped tables");
            }
            trySuccess((V) RetryWithNewProtocolResult.instance);
            return false;
        }
        else if (fail instanceof RequestTimeoutException || fail instanceof TimeoutException || fail instanceof CancellationException)
        {
            report = bookkeeping.newTimeout(txnId, keysOrRanges);
        }
        else
        {
            logger.error("Unexpected exception", fail);
            JVMStabilityInspector.inspectThrowable(fail);
            report = bookkeeping.newFailed(txnId, keysOrRanges);
        }
        report.addSuppressed(fail);
        if (!super.tryFailure(report))
            return false;

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Do not drop tables that are still the target of active Accord transactions; quiesce transactional clients first.
  2. Make application code check table existence (or catch InvalidRequestException) before/while running Accord transactions against the table.
  3. Sequence schema changes: stop writers, complete in-flight transactions, then drop the table.
  4. If hit transiently due to schema propagation lag, retry the transaction after schema agreement is reached.

Example fix

// before
session.execute("DROP TABLE ks.tbl");
// after
awaitNoInFlightAccordTxns("ks.tbl");
session.execute("DROP TABLE ks.tbl");
Defensive patterns

Strategy: validation

Validate before calling

if (driver.getMetadata().getKeyspace(ks)
        .map(k -> k.getTable(tbl)).isEmpty()) {
    throw new IllegalStateException("Table " + ks + "." + tbl + " dropped; abort Accord txn");
}

Type guard

boolean tableExists(Session s, String ks, String tbl) {
    return s.getMetadata().getKeyspace(ks)
            .flatMap(k -> k.getTable(tbl)).isPresent();
}

Try / catch

try {
    runAccordTxn(ks, tbl);
} catch (InvalidRequestException e) {
    if (e.getMessage().contains("dropped tables")) {
        recreateOrReroute(ks, tbl);
    } else throw e;
}

Prevention

When it happens

Trigger: An Accord transaction in flight references a keyspace.table that is dropped (DROP TABLE / DROP KEYSPACE) while the transaction is still executing or retrying; the failure path detects the dropped table and throws InvalidRequestException.

Common situations: Application issue of DDL concurrently with Accord transactions; schema migration scripts dropping tables while transactional workloads still issue reads/writes; nodes applying schema changes at different times.

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/3e53409ae142f30b. Report an issue: GitHub.