apache/cassandra · error · InvalidRequestException
Cannot change transactional mode from
Error message
Cannot change transactional mode from %s to %s for %s.%s before transactional migration has completed
What it means
Once a table is mid-transactional-migration, the only legal mode change is reverting to the mode the table is migrating FROM. validateAndUpdateTransactionalMigration (AlterTableStatement.java:672) throws this InvalidRequest when wasMigrating is true and the requested next.transactionalMode is anything other than prev.transactionalMigrationFrom.from, protecting the invariants of the migration state machine.
Solutions
- Revert to the original mode: set transactional_mode back to the value of transactional_migration_from to cancel the migration
- Wait for the migration to complete before changing the mode again
- Inspect the table's transactional_migration_from in system_schema.tables to know which revert target is legal
- Force an unsafe change deliberately via transactional_migration_from override only if you understand the consequences
Example fix
// table is migrating off -> accord; jumping to another mode fails // before ALTER TABLE orders WITH transactional_mode = 'unsafe_full'; // after: revert to source mode first ALTER TABLE orders WITH transactional_mode = 'off';
Defensive patterns
Strategy: validation
Validate before calling
Row r = session.execute("SELECT transactional_mode, transactional_migration_from FROM system_schema.tables WHERE keyspace_name=? AND table_name=?", ks, table).one(); boolean migrating = r != null && r.getString("transactional_migration_from") != null; // if migrating, only allow reverting to the migration-from mode Try / catch
try { session.execute(alterStmt); } catch (InvalidRequestException e) { if (e.getMessage().contains("before transactional migration has completed")) { /* revert to source mode or wait for completion */ } else throw e; } Prevention
- Serialize transactional-mode changes; never run overlapping mode ALTERs
- Query the table's migration state before altering the mode
- Only change modes in one direction and wait for completion between steps
When it happens
Trigger: While a table is migrating (e.g. off -> accord in progress), issuing ALTER TABLE WITH transactional_mode = X where X is neither the current target mode's continuation nor the original source mode (prev.transactionalMigrationFrom.from).
Common situations: Interrupting an in-progress Accord migration with an unrelated mode; scripting repeated mode toggles that land the table in an intermediate migration state; operator trying to 'jump' from migrating directly to a third mode.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Cannot change transactional mode to
- Cannot enable accord on system tables
- Counters are not supported with Accord for table
- accord.cache_size option was set incorrectly to
- accord.journal_directory must not be the same as any…
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/0653730a50bd024d.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/cql3/statements/schema/AlterTableStatement.java:672
if (modeChange && next.transactionalMode.accordIsEnabled && !DatabaseDescriptor.getAccordTransactionsEnabled())
throw ire(format("Cannot change transactional mode to %s for %s.%s with accord.enabled set to false",
next.transactionalMode, keyspaceName, tableName));
// user is manually updating migration mode, don't interfere
if (forceMigrationChange)
{
logger.warn("Forcing unsafe migration change from {} to {} with transaction mode {}", prev.transactionalMigrationFrom, next.transactionalMigrationFrom, next.transactionalMode);
return next;
}
if (!modeChange)
return next;
// if the user is trying to revert to the mode being migrated from, allow it. The migration states will be inverted when
// the transformation is applied. Otherwise throw
if (wasMigrating && next.transactionalMode != prev.transactionalMigrationFrom.from)
throw ire(format("Cannot change transactional mode from %s to %s for %s.%s before transactional migration has completed",
prev.transactionalMode, next.transactionalMode,
keyspaceName, tableName));
return next.unbuild().transactionalMigrationFrom(newMigrateFrom).build();
}
@Override
public boolean compatibleWith(ClusterMetadata metadata)
{
return metadata.directory.commonSerializationVersion.isAtLeast(Version.V0);
}
public KeyspaceMetadata apply(Epoch epoch, KeyspaceMetadata keyspace, TableMetadata table, ClusterMetadata metadata)
{
attrs.validate();
TableParams params = attrs.asAlteredTableParams(table.params);
View on GitHub (pinned to 88fd0f6a0e)