apache/cassandra · error · UnsupportedOperationException
TXN_OPS + " is a write-only table"
Error message
TXN_OPS + " is a write-only table"
What it means
The AccordDebugKeyspace virtual table `system_views.accord_txn_ops` only accepts writes (INSERTs that enqueue debug transaction operations); it has no read path. Any SELECT against it throws UnsupportedOperationException because collect() is deliberately unimplemented for this write-only table.
Solutions
- Do not SELECT from this table; it is write-only by design - only INSERT rows to enqueue transaction debug operations.
- Read the effects of enqueued operations from the intended output tables (e.g. accord_debug tables) instead.
- If a read view is needed, contribute a separate readable virtual table upstream rather than patching collect().
Example fix
// before
SELECT * FROM system_views.accord_txn_ops;
// after
-- write-only table: enqueue an op instead
INSERT INTO system_views.accord_txn_ops (txn_id, op) VALUES ('<txnId>', 'APPLY'); Defensive patterns
Strategy: validation
Validate before calling
// Treat accord_txn_ops as insert-only
if (query.trim().toUpperCase().startsWith("SELECT") && query.contains("accord_txn_ops"))
throw new IllegalArgumentException("accord_txn_ops is write-only; do not SELECT from it"); Prevention
- Remember op-queue virtual tables (accord_*_ops) are write-only by design.
- Read operation effects from readable accord debug tables instead.
- Document the insert-only contract in runbooks that use these tables.
When it happens
Trigger: Running any SELECT query (cqlsh or driver) against the TXN_OPS virtual table, e.g. `SELECT * FROM system_views.accord_txn_ops;`, which invokes the table's collect(PartitionsCollector) method.
Common situations: A developer inspects the table with SELECT first to see what's in it before inserting a debug operation, assuming virtual tables are always readable; also scripts or monitoring that enumerate all rows of every virtual table in system_views.
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
- COMMAND_STORE_OPS + " is a write-only table"
- NODE_OPS + " is a write-only table"
- metadata + " only supports single partition key queries"
- Must specify 'op'
- Unknown column " + columns[i].name.toString()
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/14280e48ee4ebaaf.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/db/virtual/AccordDebugKeyspace.java:1773
this.description = description;
}
}
private TxnOpsTable()
{
super(parse(VIRTUAL_ACCORD_DEBUG, TXN_OPS,
"Update Accord Command State",
"CREATE TABLE %s (\n" +
" txn_id text,\n" +
" command_store_id int,\n" +
" op text," +
" PRIMARY KEY (txn_id, command_store_id)" +
')', UTF8Type.instance), FAIL, UNSORTED);
}
@Override
protected void collect(PartitionsCollector collector)
{
throw new UnsupportedOperationException(TXN_OPS + " is a write-only table");
}
@Override
protected void applyRowUpdate(Object[] partitionKeys, Object[] clusteringKeys, ColumnMetadata[] columns, Object[] values)
{
TxnId txnId = TxnId.parse((String) partitionKeys[0]);
int commandStoreId = (Integer) clusteringKeys[0];
TxnOp op = tryParse(values[0], true, TxnOp.class, TxnOp::valueOf);
switch (op)
{
default: throw new UnhandledEnum(op);
case LOCALLY_ERASE_VESTIGIAL:
cleanup(txnId, commandStoreId, Cleanup.VESTIGIAL);
break;
case LOCALLY_INVALIDATE:
cleanup(txnId, commandStoreId, Cleanup.INVALIDATE);View on GitHub (pinned to 88fd0f6a0e)