prestodb/presto · error · SemanticException

INVALID_OFFSET_ROW_COUNT

INVALID_OFFSET_ROW_COUNT

Error message

Invalid OFFSET row count: %s

What it means

Analysis error from analyzeOffset: the OFFSET row count string is not a valid integer literal (Long.parseLong failed). The OFFSET argument must be a plain non-negative integer constant; expressions, decimals, or non-numeric text trigger this guard.

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java:5496

                    }
                }

                withScopeBuilder.withNamedQuery(name, withQuery);
            }

            Scope withScope = withScopeBuilder.build();
            analysis.setScope(with, withScope);
            return withScope;
        }

        private void analyzeOffset(Offset node)
        {
            long rowCount;
            try {
                rowCount = Long.parseLong(node.getRowCount());
            }
            catch (NumberFormatException e) {
                throw new SemanticException(INVALID_OFFSET_ROW_COUNT, node, "Invalid OFFSET row count: %s", node.getRowCount());
            }
            if (rowCount < 0) {
                throw new SemanticException(INVALID_OFFSET_ROW_COUNT, node, "OFFSET row count must be greater or equal to 0 (actual value: %s)", rowCount);
            }
            analysis.setOffset(node, rowCount);
        }

        private void verifySelectDistinct(QuerySpecification node, List<Expression> outputExpressions)
        {
            for (SortItem item : node.getOrderBy().get().getSortItems()) {
                Expression expression = item.getSortKey();

                if (expression instanceof LongLiteral) {
                    continue;
                }

                Expression rewrittenOrderByExpression = ExpressionTreeRewriter.rewriteWith(new OrderByExpressionRewriter(extractNamedOutputExpressions(node.getSelect())), expression);
                int index = outputExpressions.indexOf(rewrittenOrderByExpression);

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Use a plain integer literal: OFFSET 10
  2. Fix the templating so the parameter substitutes a valid integer
  3. Validate user-provided page numbers are numeric before building SQL
  4. Note: a valid negative number is rejected separately (see next error), so also clamp to >= 0

Example fix

// before
SELECT * FROM t OFFSET 'ten';
// after
SELECT * FROM t OFFSET 10;
Defensive patterns

Strategy: validation

Validate before calling

if (!offsetStr.matches("\\d+")) throw new IllegalArgumentException("OFFSET must be a non-negative integer literal: " + offsetStr);

Try / catch

try { runQuery(); } catch (SemanticException e) { if (e.getCode() == INVALID_OFFSET_ROW_COUNT.toErrorCode()) { sanitizeOffsetAndRetry(); } throw e; }

Prevention

When it happens

Trigger: SELECT * FROM t OFFSET 'abc'; or OFFSET with a non-integer literal token in the OFFSET clause.

Common situations: Templated SQL where a parameter renders as an empty or malformed string; users quoting the number; copy-paste leaving units like '10 rows' in the literal.

Related errors


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