prestodb/presto · error · PrestoException

INVALID_LIMIT_CLAUSE

INVALID_LIMIT_CLAUSE

Error message

Invalid limit: %s

What it means

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.

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/sql/planner/QueryPlanner.java:2003

    private PlanBuilder limit(PlanBuilder subPlan, QuerySpecification node)
    {
        return limit(subPlan, node.getLimit());
    }

    private PlanBuilder limit(PlanBuilder subPlan, Optional<String> limit)
    {
        if (!limit.isPresent()) {
            return subPlan;
        }

        if (!limit.get().equalsIgnoreCase("all")) {
            try {
                long limitValue = Long.parseLong(limit.get());
                subPlan = subPlan.withNewRoot(new LimitNode(subPlan.getRoot().getSourceLocation(), idAllocator.getNextId(), subPlan.getRoot(), limitValue, FINAL));
            }
            catch (NumberFormatException e) {
                throw new PrestoException(INVALID_LIMIT_CLAUSE, format("Invalid limit: %s", limit.get()));
            }
        }

        return subPlan;
    }

    // Special treatment of CallExpression
    private List<RowExpression> callArgumentsToRowExpression(FunctionHandle functionHandle, List<Expression> arguments)
    {
        return arguments.stream()
                .map(expression -> toRowExpression(
                        expression,
                        metadata,
                        session,
                        analyzeCallExpressionTypes(functionHandle, arguments, metadata, sqlParser, session, TypeProvider.viewOf(variableAllocator.getVariables())),
                        sqlPlannerContext.getTranslatorContext()))
                .collect(toImmutableList());
    }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Fix the SQL to use a plain integer literal, e.g. LIMIT 10 or FETCH FIRST 10 ROWS ONLY
  2. Use LIMIT ALL / FETCH FIRST ALL ROWS (or omit the clause) to remove the limit
  3. If SQL is generated programmatically, validate the limit value is a non-negative long before emission
  4. Check client/ORM dialect settings that may be quoting the limit value

Example fix

// before
SELECT * FROM t FETCH FIRST '25' ROWS ONLY;
// after
SELECT * FROM t FETCH FIRST 25 ROWS ONLY;
Defensive patterns

Strategy: validation

Validate before calling

// Validate LIMIT value before building SQL
String limit = "25";
if (!limit.equalsIgnoreCase("all") && !limit.matches("\\d+")) {
    throw new IllegalArgumentException("Invalid limit: " + limit);
}
String sql = "SELECT * FROM t LIMIT " + limit;

Type guard

boolean isValidLimit(String limit) {
    return limit != null && (limit.equalsIgnoreCase("all") || limit.matches("\\d+"));
}

Try / catch

try {
    result = statement.execute(sql);
} catch (PrestoException e) {
    if (e.getErrorCode().getName().equals("INVALID_LIMIT_CLAUSE")) {
        throw new IllegalArgumentException("Fix LIMIT/FETCH FIRST value to an integer or ALL", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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'.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/1767788aa78d738c. Report an issue: GitHub.