apache/cassandra · error · InvalidRequestException

Transaction Statement is unsupported when migrating away fro

Error message

Transaction Statement is unsupported when migrating away from Accord or before migration to Accord is complete for a range

What it means

TransactionStatement.execute() coordinates an Accord transaction; when AccordService.coordinate() returns a TxnResult of kind retry_new_protocol, the protocol cannot serve the transaction for the current epoch/range (either Accord migration has not completed for the range, or the cluster is migrating away from Accord), and the statement throws InvalidRequestException with UNSUPPORTED_MIGRATION text.

Source

Thrown at src/java/org/apache/cassandra/cql3/statements/TransactionStatement.java:609

        // check again since now we have query options; note that statements are quaranted to be single partition reads at this point
        for (NamedSelect assignment : assignments)
        {
            checkFalse(isSelectingMultipleClusterings(assignment.select, options), INCOMPLETE_PRIMARY_KEY_SELECT_MESSAGE, "LET assignment", assignment.select.source);
            if (assignment.select.getRestrictions().keyIsInRelation())
                checkTrue(assignment.select.getLimit(options) == DataLimits.NO_LIMIT, NO_PARTITION_IN_CLAUSE_WITH_LIMIT, "SELECT", assignment.select.source);
        }
        if (returningSelect != null && returningSelect.select.getRestrictions().keyIsInRelation())
        {
            checkTrue(returningSelect.select.getLimit(options) == DataLimits.NO_LIMIT, NO_PARTITION_IN_CLAUSE_WITH_LIMIT, "SELECT", returningSelect.select.source);
        }

        Txn txn = createTxn(state.getClientState(), options);
        if (txn == null)
            return new ResultMessage.Void();

        TxnResult txnResult = AccordService.instance().coordinate(minEpoch, txn, options.getConsistency(), requestTime);
        if (txnResult.kind() == retry_new_protocol)
            throw new InvalidRequestException(UNSUPPORTED_MIGRATION);
        TxnValidationRejection.maybeThrow(txnResult);
        TxnDataResult data = (TxnDataResult)txnResult;

        if (returningSelect != null)
        {
            @SuppressWarnings("unchecked")
            SinglePartitionReadQuery.Group<SinglePartitionReadCommand> selectQuery = (SinglePartitionReadQuery.Group<SinglePartitionReadCommand>) returningSelect.select.getQuery(options, 0);
            Selection.Selectors selectors = returningSelect.select.getSelection().newSelectors(options);
            long atMicros = data.atMicros;
            FunctionContext context = new FunctionContext.MicrosFunctionContext(atMicros)
            {
                @Override public QueryOptions options() { return options; }
            };
            ResultSetBuilder result = new ResultSetBuilder(resultMetadata, context, selectors, false);
            long atSeconds = atMicros / 1000_000;
            if (selectQuery.queries.size() == 1)
            {
                TxnDataKeyValue partition = (TxnDataKeyValue)data.get(txnDataName(RETURNING));

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Enable/complete the Accord migration for the cluster (accord config and migration tooling) before issuing transaction statements
  2. Retry after migration state converges (retry_new_protocol indicates protocol timing)
  3. Use standard (non-transactional) CQL statements if Accord is intentionally disabled
  4. Check cluster epoch/migration status (AccordService/jmx logs) to confirm the range is on the Accord protocol

Example fix

// before (accord not migrated)
BEGIN TRANSACTION
  SELECT ... ;
COMMIT TRANSACTION;
// after
-- either enable/complete Accord migration in cassandra.yaml,
-- or use plain statements:
SELECT ... FROM ks.t WHERE ...;
Defensive patterns

Strategy: retry

Validate before calling

if (!clusterAccordMigrationComplete()) throw new Error('Accord not ready for transaction statements; use plain CQL');

Try / catch

try { session.execute(txnStmt); } catch (e) { if (/migrat.*Accord/.test(e.message)) { await waitForAccordEpochConvergence(); return session.execute(txnStmt); } throw e; }

Prevention

When it happens

Trigger: Running BEGIN TRANSACTION ... statements while the cluster is in a state where Accord is disabled/partially migrated (e.g. before the Accord migration has been driven to completion for the token range, or during a migration-away procedure), causing coordinate() to answer retry_new_protocol.

Common situations: Testing transactional CQL on a cluster where accord is not enabled via feature flags/config; upgrading/rolling back across a version boundary that changes Accord participation; issuing transactions immediately after node bootstrap before epoch/migration state converges.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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