apache/cassandra · error · InvalidRequestException

Cannot add a counter column to Accord table %s.%s with trans

Error message

Cannot add a counter column to Accord table %s.%s with transactional mode %s and transactional migration from %s

What it means

Counter columns are incompatible with Accord-based transactions. ALTER TABLE ... ADD of a counter column is rejected when the table has transactionalMode with Accord enabled or is migrating from Accord, because Accord's replicated transaction protocol cannot support counter columns.

Source

Thrown at src/java/org/apache/cassandra/cql3/statements/schema/AlterTableStatement.java:361

                               Column column,
                               boolean ifColumnNotExists,
                               TableMetadata.Builder tableBuilder,
                               Views.Builder viewsBuilder)
        {
            ColumnIdentifier name = column.name;
            AbstractType<?> type = column.type.prepare(keyspaceName, keyspace.types).getType();
            boolean isStatic = column.isStatic;
            ColumnMask mask = column.mask == null ? null : column.mask.prepare(keyspaceName, tableName, name, type, keyspace.userFunctions);
            ColumnConstraints columnConstraints = column.constraints == null ? ColumnConstraints.NO_OP : column.constraints.prepare(name);

            if (null != tableBuilder.getColumn(name)) {
                if (!ifColumnNotExists)
                    throw ire("Column with name '%s' already exists", name);
                return;
            }

            if (type.isCounter() && (table.params.transactionalMode.accordIsEnabled || table.params.transactionalMigrationFrom.migratingFromAccord()))
                throw ire(format(ACCORD_COUNTER_COLUMN_UNSUPPORTED, keyspaceName, tableName, table.params.transactionalMode, table.params.transactionalMigrationFrom));

            if (table.isCompactTable())
                throw ire("Cannot add new column to a COMPACT STORAGE table");

            if (isStatic && table.clusteringColumns().isEmpty())
                throw ire("Static columns are only useful (and thus allowed) if the table has at least one clustering column");

            // check for nested non-frozen UDTs or collections in a non-frozen UDT
            if (type.isUDT() && type.isMultiCell())
            {
                for (AbstractType<?> fieldType : ((UserType) type).fieldTypes())
                {
                    if (fieldType.isMultiCell())
                        throw ire("Non-frozen UDTs with nested non-frozen collections are not supported for column " + column.name);
                }
            }

            ColumnMetadata droppedColumn = table.getDroppedColumn(name.bytes);

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Use a non-counter column type (e.g. int/bigint with application-side increments inside transactions)
  2. If counters are required, keep the table in a non-Accord transactional mode (review whether Accord is actually needed for that table)
  3. Split counters into a separate non-transactional table

Example fix

// before
session.execute("ALTER TABLE my_app.accord_events ADD hits counter");
// after
// counters are unsupported on Accord tables; use an owned bigint updated in a transaction
session.execute("ALTER TABLE my_app.accord_events ADD hits bigint");
Defensive patterns

Strategy: validation

Validate before calling

String mode = session.execute("SELECT transactional_mode FROM system_schema.tables WHERE keyspace_name=? AND table_name=?", ks, table).one().getString("transactional_mode");
if ("counter".equals(newType) && mode != null && mode.toLowerCase().contains("accord"))
    throw new IllegalArgumentException("Counters unsupported on Accord tables");

Try / catch

try {
    session.execute(alter);
} catch (InvalidRequestException e) {
    if (e.getMessage().contains("Accord table"))
        log.error("Cannot add counter column to Accord-enabled table {}", tableName);
    else throw e;
}

Prevention

When it happens

Trigger: ALTER TABLE ... ADD col counter where table.params.transactionalMode.accordIsEnabled() is true or transactionalMigrationFrom.migratingFromAccord() is true, on tables using txn modes like 'test.zone_serialize_accord' or similar Accord-enabled settings

Common situations: Adding legacy counter columns to tables migrated to Accord transactional mode during the Accord rollout; schema scripts written for classic Cassandra applied to Accord-enabled tables; migration tooling that doesn't check transactional_mode.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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