{"record":{"id":"1767788aa78d738c","repo":"prestodb/presto","slug":"invalid-limit-clause","errorCode":"INVALID_LIMIT_CLAUSE","errorMessage":"Invalid limit: %s","messagePattern":"Invalid limit: (.+?)","errorType":"error_code","errorClass":"PrestoException","httpStatus":null,"severity":"error","filePath":"presto-main-base/src/main/java/com/facebook/presto/sql/planner/QueryPlanner.java","lineNumber":2003,"sourceCode":"\n    private PlanBuilder limit(PlanBuilder subPlan, QuerySpecification node)\n    {\n        return limit(subPlan, node.getLimit());\n    }\n\n    private PlanBuilder limit(PlanBuilder subPlan, Optional<String> limit)\n    {\n        if (!limit.isPresent()) {\n            return subPlan;\n        }\n\n        if (!limit.get().equalsIgnoreCase(\"all\")) {\n            try {\n                long limitValue = Long.parseLong(limit.get());\n                subPlan = subPlan.withNewRoot(new LimitNode(subPlan.getRoot().getSourceLocation(), idAllocator.getNextId(), subPlan.getRoot(), limitValue, FINAL));\n            }\n            catch (NumberFormatException e) {\n                throw new PrestoException(INVALID_LIMIT_CLAUSE, format(\"Invalid limit: %s\", limit.get()));\n            }\n        }\n\n        return subPlan;\n    }\n\n    // Special treatment of CallExpression\n    private List<RowExpression> callArgumentsToRowExpression(FunctionHandle functionHandle, List<Expression> arguments)\n    {\n        return arguments.stream()\n                .map(expression -> toRowExpression(\n                        expression,\n                        metadata,\n                        session,\n                        analyzeCallExpressionTypes(functionHandle, arguments, metadata, sqlParser, session, TypeProvider.viewOf(variableAllocator.getVariables())),\n                        sqlPlannerContext.getTranslatorContext()))\n                .collect(toImmutableList());\n    }","sourceCodeStart":1985,"sourceCodeEnd":2021,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main-base/src/main/java/com/facebook/presto/sql/planner/QueryPlanner.java#L1985-L2021","documentation":"When planning a FETCH FIRST/LIMIT clause, QueryPlanner accepts either the literal 'ALL' or a parseable long. If the limit string is neither 'all' (case-insensitive) nor a valid long, Long.parseLong throws NumberFormatException, which is rethrown as PrestoException with INVALID_LIMIT_CLAUSE.","triggerScenarios":"A query whose LIMIT/FETCH FIRST value, after analysis, is a non-numeric string other than 'ALL' — e.g. FETCH FIRST 'ten' ROWS ONLY, or a parameterized/quoted limit that analysis resolved to a bad literal.","commonSituations":"Hand-written SQL with quoted or malformed limit values; generated SQL where a limit placeholder was substituted with a non-numeric string; dialect-translation bugs producing LIMIT 'N'.","solutions":["Fix the SQL to use a plain integer literal, e.g. LIMIT 10 or FETCH FIRST 10 ROWS ONLY","Use LIMIT ALL / FETCH FIRST ALL ROWS (or omit the clause) to remove the limit","If SQL is generated programmatically, validate the limit value is a non-negative long before emission","Check client/ORM dialect settings that may be quoting the limit value"],"exampleFix":"// before\nSELECT * FROM t FETCH FIRST '25' ROWS ONLY;\n// after\nSELECT * FROM t FETCH FIRST 25 ROWS ONLY;","handlingStrategy":"validation","validationCode":"// Validate LIMIT value before building SQL\nString limit = \"25\";\nif (!limit.equalsIgnoreCase(\"all\") && !limit.matches(\"\\\\d+\")) {\n    throw new IllegalArgumentException(\"Invalid limit: \" + limit);\n}\nString sql = \"SELECT * FROM t LIMIT \" + limit;","typeGuard":"boolean isValidLimit(String limit) {\n    return limit != null && (limit.equalsIgnoreCase(\"all\") || limit.matches(\"\\\\d+\"));\n}","tryCatchPattern":"try {\n    result = statement.execute(sql);\n} catch (PrestoException e) {\n    if (e.getErrorCode().getName().equals(\"INVALID_LIMIT_CLAUSE\")) {\n        throw new IllegalArgumentException(\"Fix LIMIT/FETCH FIRST value to an integer or ALL\", e);\n    }\n    throw e;\n}","preventionTips":["Never quote LIMIT values in generated SQL","Sanitize user-supplied page sizes to non-negative integers before SQL emission","Use LIMIT ALL (or omit) instead of non-numeric sentinels","Test SQL generation templates for limit injection points"],"tags":["presto","planner","sql-syntax","limit"],"backgroundTag":"invalid-limit-clause","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"}