apache/cassandra · error · TimeQuotaExceededException
Command '${command}' took too long (${execTime}ms >= ${quota
Error message
Command '${command}' took too long (${execTime}ms >= ${quota}ms). What it means
QueryController.checkpoint() enforces a per-query time quota for SASI query execution. Each time getPartition() (and other checkpoint call sites) runs, it compares elapsed nanos against executionQuota and throws TimeQuotaExceededException once the query has run longer than allowed, preventing long-running index scans from monopolizing coordinator resources.
Source
Thrown at src/java/org/apache/cassandra/index/sasi/plan/QueryController.java:172
for (Map.Entry<Expression, Set<SSTableIndex>> e : view)
{
RangeIterator<Long, Token> index = TermIterator.build(e.getKey(), e.getValue());
builder.add(index);
perIndexUnions.add(index);
}
resources.put(expressions, perIndexUnions);
return builder;
}
public void checkpoint()
{
long executionTime = (nanoTime() - executionStart);
if (executionTime >= executionQuota)
throw new TimeQuotaExceededException(
"Command '" + command + "' took too long " +
"(" + TimeUnit.NANOSECONDS.toMillis(executionTime) +
" >= " + TimeUnit.NANOSECONDS.toMillis(executionQuota) + "ms).");
}
public void releaseIndexes(Operation operation)
{
if (operation.expressions != null)
releaseIndexes(resources.remove(operation.expressions.values()));
}
private void releaseIndexes(List<RangeIterator<Long, Token>> indexes)
{
if (indexes == null)
return;
indexes.forEach(FileUtils::closeQuietly);
}View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Rewrite the query with more selective predicates (tighter ranges, additional EQ terms) so fewer partitions are scanned
- Raise the quota indirectly by increasing the read timeouts it derives from (read_request_timeout_in_ms, range_request_timeout_in_ms) in cassandra.yaml
- Ensure SASI indexes exist on the columns used so the planner narrows results before row evaluation
- Use paging (LIMIT with paging state) and avoid unbounded broad scans in application code
Example fix
// before SELECT * FROM ks.logs WHERE message LIKE '%error%'; // scans whole index, exceeds quota // after SELECT * FROM ks.logs WHERE app = 'billing' AND day = '2026-09-09' AND message LIKE 'error%'; // selective EQ terms first
Defensive patterns
Strategy: try-catch
Validate before calling
// Check selectivity before issuing: count matching rows with a bounded query first cqlsh> SELECT COUNT(*) FROM ks.logs WHERE app='billing' AND day='2026-09-09' LIMIT 100000;
Try / catch
try {
ResultSet rs = session.execute(sasiQuery);
} catch (TimeQuotaExceededException e) {
// narrow the predicates or split the query into smaller time-bounded slices
retryWithNarrowerBounds(e);
} Prevention
- Always include at least one highly selective EQ term in SASI queries
- Page through large result sets instead of issuing unbounded scans
- Tune read timeouts deliberately; do not set them below realistic index-scan durations
- Monitor for queries approaching the quota and alert before they time out
When it happens
Trigger: A SASI SELECT with many expressions or a broad term match (low selectivity, e.g. a range or prefix that hits millions of partitions) that takes longer than the quota (derived from the read timeout / cross_node_timeout settings) before checkpoint() is called from getPartition().
Common situations: Production queries with non-selective SASI predicates hitting huge partitions; quotas configured too low on busy clusters; queries that were fine before a data-size increase now exceed the execution window.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
- User defined function %s ran longer than %dms
- Some operations timed out, details available at debug level
- ${executor.name} not terminated
- SASI indexes are disabled. Enable in cassandra.yaml to use.
- TombstoneOverwhelmingException
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/62ff42ef08fadbf8.
Report an issue: GitHub.