apache/cassandra · error · UnsupportedOperationException

NODE_OPS + " is a write-only table"

Error message

NODE_OPS + " is a write-only table"

What it means

The `accord_node_ops` virtual table is write-only: it accepts INSERTs to enqueue node-level debug operations but implements no read path, so any SELECT throws UnsupportedOperationException from collect().

Solutions

  1. Do not SELECT from accord_node_ops; only INSERT rows to trigger node debug operations.
  2. Observe operation results via the appropriate readable debug/status tables or node logs.
  3. If a read view is required, add a separate readable virtual table upstream.

Example fix

// before
SELECT * FROM system_views.accord_node_ops;
// after
INSERT INTO system_views.accord_node_ops (node_id, op) VALUES (1, '<op>');
Defensive patterns

Strategy: validation

Validate before calling

if (query.trim().toUpperCase().startsWith("SELECT") && query.contains("accord_node_ops"))
    throw new IllegalArgumentException("accord_node_ops is write-only; do not SELECT from it");

Prevention

When it happens

Trigger: Running a SELECT against system_views.accord_node_ops, e.g. `SELECT * FROM system_views.accord_node_ops;`, which calls the unimplemented collect(PartitionsCollector).

Common situations: Inspecting the table before writing an op; automation enumerating all virtual tables; confusing this op-queue table with the readable accord debug status tables.

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


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

Appendix: source

Thrown at src/java/org/apache/cassandra/db/virtual/AccordDebugKeyspace.java:1950

            {
                this.description = description;
            }
        }
        private NodeOpsTable()
        {
            super(parse(VIRTUAL_ACCORD_DEBUG, NODE_OPS,
                        "Update Accord Node State",
                        "CREATE TABLE %s (\n" +
                        "  node_id int,\n" +
                        "  op text," +
                        "  PRIMARY KEY (node_id)" +
                        ')', Int32Type.instance), FAIL, UNSORTED);
        }

        @Override
        protected void collect(PartitionsCollector collector)
        {
            throw new UnsupportedOperationException(NODE_OPS + " is a write-only table");
        }

        @Override
        protected void applyRowUpdate(Object[] partitionKeys, Object[] clusteringKeys, ColumnMetadata[] columns, Object[] values)
        {
            NodeId nodeId = new NodeId((Integer) partitionKeys[0]);
            Set<NodeId> nodeIds = Collections.singleton(nodeId);
            NodeOp op = tryParse(values[0], true, NodeOp.class, NodeOp::valueOf);

            switch (op)
            {
                default: throw new UnhandledEnum(op);
                case MARK_STALE:
                    AccordOperations.instance.accordMarkStale(nodeIds);
                    break;
                case UNMARK_STALE:
                    AccordOperations.instance.accordMarkRejoining(nodeIds);
                    break;

View on GitHub (pinned to 88fd0f6a0e)