apache/cassandra · error · InvalidRequestException
May only delete on txn_id and id_micros
Error message
May only delete on txn_id and id_micros
What it means
In the AccordDebugKeyspace txn_id-keyed virtual table, range tombstones over the clustering columns are only meaningful when the range is expressed on the single clustering column id_micros. applyRangeTombstone throws this error when the DELETE's clustering range involves more than one clustering column bound (starts.length > 1 or ends.length > 1), since the table cannot map multi-column ranges onto a single id_micros interval.
Solutions
- Restrict the DELETE range to only the id_micros clustering column: `DELETE FROM ... WHERE txn_id = '...' AND id_micros >= x AND id_micros <= y`.
- Delete individual rows one at a time instead of a multi-column range.
- Delete the entire partition (`DELETE FROM ... WHERE txn_id = '...';`) if the table supports it.
- If broader cleanup is needed, use the underlying Accord state tooling rather than this debug table.
Example fix
// before DELETE FROM system.accord_debug WHERE txn_id = '...' AND id_micros > 5 AND some_col < 10; // multi-column range // after DELETE FROM system.accord_debug WHERE txn_id = '...' AND id_micros > 5; // single-column range only
Defensive patterns
Strategy: validation
Validate before calling
// Ensure the DELETE range touches only the id_micros clustering column
if (whereClauseColumns.stream().filter(c -> !c.equals("txn_id") && !c.equals("id_micros")).count() > 0)
throw new IllegalArgumentException("Only txn_id and id_micros predicates allowed"); Try / catch
try { session.execute(deleteStmt); }
catch (InvalidRequestException e) { if (e.getMessage().equals("May only delete on txn_id and id_micros")) { /* rewrite range on id_micros only */ } else throw e; } Prevention
- Remember this debug table has a single effective clustering column for ranges.
- Express cleanup ranges purely on id_micros bounds.
- Use per-row deletes or full-partition deletes for anything more complex.
When it happens
Trigger: Executing a ranged DELETE like `DELETE FROM table WHERE txn_id = '...' AND id_micros > 1 AND other_col < 5` (or any multi-clustering-column range) against this debug virtual table.
Common situations: Administrators cleaning up Accord txn records with generic range-delete queries modeled after normal tables with composite clustering keys; debugging scripts assuming full CQL range semantics on virtual tables.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Can only unset '" + name + "'
- Cannot filter this table by partial partition key
- Cannot update '" + name + "'
- metadata + " currently only supports querying single…
- Accord transaction uses dropped tables
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/519ee88865e85324.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/db/virtual/AccordDebugKeyspace.java:1240
" command_store_id int,\n" +
" remote_node_id int,\n" +
" message text,\n" +
" PRIMARY KEY (txn_id, id_micros, event, at_micros)" +
')', TxnIdUtf8Type.instance), FAIL, UNSORTED, UNSORTED);
}
@Override
protected void applyPartitionDeletion(Object[] partitionKeys)
{
TxnId txnId = TxnId.parse((String)partitionKeys[0]);
tracing().eraseEvents(txnId);
}
@Override
protected void applyRangeTombstone(Object[] partitionKeys, Object[] starts, boolean startInclusive, Object[] ends, boolean endInclusive)
{
TxnId txnId = TxnId.parse((String) partitionKeys[0]);
if (starts.length > 1 || ends.length > 1) throw invalidRequest("May only delete on txn_id and id_micros");
long minId = Long.MIN_VALUE, maxId = Long.MAX_VALUE;
if (starts.length == 1)
{
minId = ((Long)starts[0]);
if (!startInclusive && minId < Long.MAX_VALUE)
++minId;
}
if (ends.length == 1)
{
maxId = ((Long)ends[0]);
if (!endInclusive && maxId > Long.MIN_VALUE)
--maxId;
}
tracing().eraseEventsBetween(txnId, minId, maxId);
}
@OverrideView on GitHub (pinned to 88fd0f6a0e)