apache/cassandra · error · InvalidRequestException

Row deletion is not supported by table

Error message

Row deletion is not supported by table %s

What it means

AbstractMutableVirtualTable's default applyRowDeletion throws this invalid-request error: single-row DELETEs are not supported unless the concrete virtual table overrides this method. Related defaults also reject column deletion (applyColumnDeletion).

Solutions

  1. Consult the virtual table's documentation to confirm which mutations it permits.
  2. Operate on the underlying state (via nodetool or the appropriate API) instead of DELETE.
  3. If you implement the table, override applyRowDeletion(ColumnValues, ColumnValues) to support row deletes.
Defensive patterns

Strategy: try-catch

Try / catch

try {
    session.execute("DELETE FROM some_virtual_table WHERE pk = ? AND ck = ?", pk, ck);
} catch (InvalidQueryException e) {
    if (e.getMessage().contains("Row deletion is not supported")) {
        // use nodetool/admin API to remove the underlying entry instead
    }
}

Prevention

When it happens

Trigger: Executing 'DELETE FROM <virtual_table> WHERE <partition key> AND <clustering key>' against a virtual table extending AbstractMutableVirtualTable that has not overridden applyRowDeletion(ColumnValues, ColumnValues).

Common situations: Users deleting individual rows from virtual tables that look writable; automated jobs pruning virtual-table entries; attempting to remove entries such as failed-endpoint or sstable-task rows.

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/62b1647a7a869162. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/db/virtual/AbstractMutableVirtualTable.java:150

        ColumnValues end = ColumnValues.from(metadata(), endBound);
        BoundType endType = boundType(endBound);

        return Range.range(start, startType, end, endType);
    }

    private static BoundType boundType(ClusteringBound<?> bound)
    {
        return bound.isInclusive() ? BoundType.CLOSED : BoundType.OPEN;
    }

    protected void applyRangeTombstone(ColumnValues partitionKey, Range<ColumnValues> range)
    {
        throw invalidRequest("Range deletion is not supported by table %s", metadata);
    }

    protected void applyRowDeletion(ColumnValues partitionKey, ColumnValues clusteringColumns)
    {
        throw invalidRequest("Row deletion is not supported by table %s", metadata);
    }

    protected void applyColumnDeletion(ColumnValues partitionKey, ColumnValues clusteringColumns, String columnName)
    {
        throw invalidRequest("Column deletion is not supported by table %s", metadata);
    }

    protected void applyColumnUpdate(ColumnValues partitionKey,
                                     ColumnValues clusteringColumns,
                                     Optional<ColumnValue> columnValue)
    {
        throw invalidRequest("Column modification is not supported by table %s", metadata);
    }

    private static String columnName(Cell<?> cell)
    {
        return cell.column().name.toCQLString();
    }

View on GitHub (pinned to 88fd0f6a0e)