{"record":{"id":"9ca988adc5fe7665","repo":"apache/cassandra","slug":"cannot-add-a-counter-column-to-accord-table-s-s","errorCode":null,"errorMessage":"Cannot add a counter column to Accord table %s.%s with transactional mode %s and transactional migration from %s","messagePattern":"Cannot add a counter column to Accord table (.+?)\\.(.+?) with transactional mode (.+?) and transactional migration from (.+?)","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/statements/schema/AlterTableStatement.java","lineNumber":361,"sourceCode":"                               Column column,\n                               boolean ifColumnNotExists,\n                               TableMetadata.Builder tableBuilder,\n                               Views.Builder viewsBuilder)\n        {\n            ColumnIdentifier name = column.name;\n            AbstractType<?> type = column.type.prepare(keyspaceName, keyspace.types).getType();\n            boolean isStatic = column.isStatic;\n            ColumnMask mask = column.mask == null ? null : column.mask.prepare(keyspaceName, tableName, name, type, keyspace.userFunctions);\n            ColumnConstraints columnConstraints = column.constraints == null ? ColumnConstraints.NO_OP : column.constraints.prepare(name);\n\n            if (null != tableBuilder.getColumn(name)) {\n                if (!ifColumnNotExists)\n                    throw ire(\"Column with name '%s' already exists\", name);\n                return;\n            }\n\n            if (type.isCounter() && (table.params.transactionalMode.accordIsEnabled || table.params.transactionalMigrationFrom.migratingFromAccord()))\n                throw ire(format(ACCORD_COUNTER_COLUMN_UNSUPPORTED, keyspaceName, tableName, table.params.transactionalMode, table.params.transactionalMigrationFrom));\n\n            if (table.isCompactTable())\n                throw ire(\"Cannot add new column to a COMPACT STORAGE table\");\n\n            if (isStatic && table.clusteringColumns().isEmpty())\n                throw ire(\"Static columns are only useful (and thus allowed) if the table has at least one clustering column\");\n\n            // check for nested non-frozen UDTs or collections in a non-frozen UDT\n            if (type.isUDT() && type.isMultiCell())\n            {\n                for (AbstractType<?> fieldType : ((UserType) type).fieldTypes())\n                {\n                    if (fieldType.isMultiCell())\n                        throw ire(\"Non-frozen UDTs with nested non-frozen collections are not supported for column \" + column.name);\n                }\n            }\n\n            ColumnMetadata droppedColumn = table.getDroppedColumn(name.bytes);","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/statements/schema/AlterTableStatement.java#L343-L379","documentation":"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.","triggerScenarios":"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","commonSituations":"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.","solutions":["Use a non-counter column type (e.g. int/bigint with application-side increments inside transactions)","If counters are required, keep the table in a non-Accord transactional mode (review whether Accord is actually needed for that table)","Split counters into a separate non-transactional table"],"exampleFix":"// before\nsession.execute(\"ALTER TABLE my_app.accord_events ADD hits counter\");\n// after\n// counters are unsupported on Accord tables; use an owned bigint updated in a transaction\nsession.execute(\"ALTER TABLE my_app.accord_events ADD hits bigint\");","handlingStrategy":"validation","validationCode":"String mode = session.execute(\"SELECT transactional_mode FROM system_schema.tables WHERE keyspace_name=? AND table_name=?\", ks, table).one().getString(\"transactional_mode\");\nif (\"counter\".equals(newType) && mode != null && mode.toLowerCase().contains(\"accord\"))\n    throw new IllegalArgumentException(\"Counters unsupported on Accord tables\");","typeGuard":null,"tryCatchPattern":"try {\n    session.execute(alter);\n} catch (InvalidRequestException e) {\n    if (e.getMessage().contains(\"Accord table\"))\n        log.error(\"Cannot add counter column to Accord-enabled table {}\", tableName);\n    else throw e;\n}","preventionTips":["Check transactional_mode before adding columns to a table","Design Accord tables without counter columns from the start","Keep counters in dedicated non-transactional tables"],"tags":["cassandra","cql","ddl","accord","counter"],"backgroundTag":"conflicting-config-options","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}