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
- Enable/complete the Accord migration for the cluster (accord config and migration tooling) before issuing transaction statements
- Retry after migration state converges (retry_new_protocol indicates protocol timing)
- Use standard (non-transactional) CQL statements if Accord is intentionally disabled
- 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
- Only issue BEGIN TRANSACTION statements after Accord migration is complete cluster-wide
- Gate transactional paths on cluster/epoch readiness checks
- Fall back to non-transactional CQL when Accord is disabled for a range
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
- No ORDER BY clause allowed within a transaction; %s statemen
- No GROUP BY clause allowed within a transaction; %s statemen
- Accord transactions are disabled on table (See transactional
- Element selection not supported for column %s of type %s
- Invalid reference type %s (%s) for "%s" of type %s
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/bc155c2bf0ba10cf.
Report an issue: GitHub.