{"record":{"id":"04879b99bed05663","repo":"prestodb/presto","slug":"druid-query-generator-failure-04879b","errorCode":"DRUID_QUERY_GENERATOR_FAILURE","errorMessage":"Invalid limit: ","messagePattern":"Invalid limit: ","errorType":"error_code","errorClass":"PrestoException","httpStatus":null,"severity":"error","filePath":"presto-druid/src/main/java/com/facebook/presto/druid/DruidQueryGeneratorContext.java","lineNumber":147,"sourceCode":"\n    public DruidQueryGeneratorContext withProject(Map<VariableReferenceExpression, Selection> newSelections)\n    {\n        return new DruidQueryGeneratorContext(\n                newSelections,\n                from,\n                filter,\n                limit,\n                aggregations,\n                groupByColumns,\n                variablesInAggregation,\n                hiddenColumnSet,\n                tableScanNodeId);\n    }\n\n    public DruidQueryGeneratorContext withLimit(long limit)\n    {\n        if (limit <= 0 || limit > Long.MAX_VALUE) {\n            throw new PrestoException(DRUID_QUERY_GENERATOR_FAILURE, \"Invalid limit: \" + limit);\n        }\n        checkState(!hasLimit(), \"Limit already exists. Druid doesn't support limit on top of another limit\");\n        return new DruidQueryGeneratorContext(\n                selections,\n                from,\n                filter,\n                OptionalLong.of(limit),\n                aggregations,\n                groupByColumns,\n                variablesInAggregation,\n                hiddenColumnSet,\n                tableScanNodeId);\n    }\n\n    public DruidQueryGeneratorContext withAggregation(\n            Map<VariableReferenceExpression, Selection> newSelections,\n            Map<VariableReferenceExpression, Selection> newGroupByColumns,\n            int newAggregations,","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-druid/src/main/java/com/facebook/presto/druid/DruidQueryGeneratorContext.java#L129-L165","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nSELECT k FROM druid_table LIMIT 0; -- throws Invalid limit: 0\n// after\nSELECT k FROM druid_table LIMIT 1; -- or issue a metadata-only probe","handlingStrategy":"validation","validationCode":"void validateLimit(long limit) {\n    if (limit <= 0 || limit > Long.MAX_VALUE) {\n        throw new IllegalArgumentException(\"LIMIT must be positive, got: \" + limit);\n    }\n}","typeGuard":"boolean isValidLimit(Long limit) { return limit != null && limit > 0 && limit < Long.MAX_VALUE; }","tryCatchPattern":"try { return context.withLimit(limit); }\ncatch (PrestoException e) {\n    if (DRUID_QUERY_GENERATOR_FAILURE.getCode().equals(e.getErrorCode().getCode())) {\n        return emptyResultPlan(); // limit <= 0 yields no rows\n    }\n    throw e;\n}","preventionTips":["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"],"tags":["druid","limit","pushdown","validation"],"backgroundTag":"invalid-limit-pushdown","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}