prestodb/presto · error · PrestoException
DRUID_QUERY_GENERATOR_FAILURE
DRUID_QUERY_GENERATOR_FAILURE
Error message
Invalid limit:
What it means
withLimit validates the LIMIT value before embedding it in the generated Druid query. A non-positive value or one exceeding Long.MAX_VALUE is rejected with DRUID_QUERY_GENERATOR_FAILURE, since Druid queries require a valid positive limit.
Source
Thrown at presto-druid/src/main/java/com/facebook/presto/druid/DruidQueryGeneratorContext.java:147
public DruidQueryGeneratorContext withProject(Map<VariableReferenceExpression, Selection> newSelections)
{
return new DruidQueryGeneratorContext(
newSelections,
from,
filter,
limit,
aggregations,
groupByColumns,
variablesInAggregation,
hiddenColumnSet,
tableScanNodeId);
}
public DruidQueryGeneratorContext withLimit(long limit)
{
if (limit <= 0 || limit > Long.MAX_VALUE) {
throw new PrestoException(DRUID_QUERY_GENERATOR_FAILURE, "Invalid limit: " + limit);
}
checkState(!hasLimit(), "Limit already exists. Druid doesn't support limit on top of another limit");
return new DruidQueryGeneratorContext(
selections,
from,
filter,
OptionalLong.of(limit),
aggregations,
groupByColumns,
variablesInAggregation,
hiddenColumnSet,
tableScanNodeId);
}
public DruidQueryGeneratorContext withAggregation(
Map<VariableReferenceExpression, Selection> newSelections,
Map<VariableReferenceExpression, Selection> newGroupByColumns,
int newAggregations,View on GitHub (pinned to 55bb57d202)
Solutions
- Remove LIMIT 0 from the query or let the optimizer replace it with an empty relation before pushdown
- Use a positive LIMIT value in the query
- Guard at the connector level: convert limit <= 0 to a zero-row plan instead of throwing in the generator
- Upgrade Presto so the optimizer eliminates 0-limit nodes before Druid plan matching
Example fix
// before SELECT k FROM druid_table LIMIT 0; -- throws Invalid limit: 0 // after SELECT k FROM druid_table LIMIT 1; -- or issue a metadata-only probe
Defensive patterns
Strategy: validation
Validate before calling
void validateLimit(long limit) {
if (limit <= 0 || limit > Long.MAX_VALUE) {
throw new IllegalArgumentException("LIMIT must be positive, got: " + limit);
}
} Type guard
boolean isValidLimit(Long limit) { return limit != null && limit > 0 && limit < Long.MAX_VALUE; } Try / catch
try { return context.withLimit(limit); }
catch (PrestoException e) {
if (DRUID_QUERY_GENERATOR_FAILURE.getCode().equals(e.getErrorCode().getCode())) {
return emptyResultPlan(); // limit <= 0 yields no rows
}
throw e;
} Prevention
- Never emit LIMIT 0; let the optimizer short-circuit to an empty relation first
- Validate user-supplied LIMIT inputs in BI/tools before issuing SQL
- Treat LIMIT 0 queries as metadata probes outside the pushdown path
- Add a unit test for visitLimit with limit=0 and limit=Long.MAX_VALUE
When it happens
Trigger: visitLimit pushes a LimitNode whose count is <= 0 (degenerate plan after optimization) or, defensively, a limit greater than Long.MAX_VALUE — practically only the limit <= 0 path is reachable from normal planning.
Common situations: Queries with LIMIT 0 (e.g. generated by tools or schema-exploration probes); plans where optimizer-produced limits of 0 were still routed to pushdown rather than an empty-result node.
Related errors
- CLICKHOUSE_QUERY_GENERATOR_FAILURE
- DRUID_PUSHDOWN_UNSUPPORTED_EXPRESSION
- DRUID_PUSHDOWN_UNSUPPORTED_EXPRESSION
- DRUID_QUERY_GENERATOR_FAILURE
- DRUID_PUSHDOWN_UNSUPPORTED_EXPRESSION
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/04879b99bed05663.
Report an issue: GitHub.