prestodb/presto · error · SemanticException

INVALID_PARAMETER_USAGE

INVALID_PARAMETER_USAGE

Error message

Subscript expression on ROW requires a constant index

What it means

ROW subscript (rowExpr[i]) is resolved by hand in the analyzer rather than via a dedicated operator, so the index must be a constant LongLiteral. A dynamic index expression (column, function call, arithmetic) cannot be used and triggers INVALID_PARAMETER_USAGE.

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/ExpressionAnalyzer.java:808

        }

        private Type getVarcharType(Expression value, StackableAstVisitorContext<Context> context)
        {
            Type type = process(value, context);
            if (!(type instanceof VarcharType)) {
                return VARCHAR;
            }
            return type;
        }

        @Override
        protected Type visitSubscriptExpression(SubscriptExpression node, StackableAstVisitorContext<Context> context)
        {
            Type baseType = process(node.getBase(), context);
            // Subscript on Row hasn't got a dedicated operator. Its Type is resolved by hand.
            if (baseType instanceof RowType) {
                if (!(node.getIndex() instanceof LongLiteral)) {
                    throw new SemanticException(
                            INVALID_PARAMETER_USAGE,
                            node.getIndex(),
                            "Subscript expression on ROW requires a constant index");
                }
                Type indexType = process(node.getIndex(), context);
                if (!indexType.equals(INTEGER)) {
                    throw new SemanticException(
                            TYPE_MISMATCH,
                            node.getIndex(),
                            "Subscript expression on ROW requires integer index, found %s", indexType);
                }
                int indexValue = toIntExact(((LongLiteral) node.getIndex()).getValue());
                if (indexValue <= 0) {
                    throw new SemanticException(
                            INVALID_PARAMETER_USAGE,
                            node.getIndex(),
                            "Invalid subscript index: %s. ROW indices start at 1", indexValue);
                }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Use a literal integer index, e.g. my_row[1]
  2. If dynamic access is needed, convert the ROW to a map or use a CASE expression over literal indices
  3. Extract the field in application code instead of SQL

Example fix

// before
SELECT my_row[idx] FROM t
// after
SELECT CASE idx WHEN 1 THEN my_row[1] WHEN 2 THEN my_row[2] END FROM t
Defensive patterns

Strategy: validation

Validate before calling

if (isRowType(baseType) && !(indexExpr instanceof LongLiteral)) {
    throw new IllegalArgumentException("ROW subscript requires a constant integer literal");
}

Type guard

boolean isConstantRowIndex(Expression index) { return index instanceof LongLiteral; }

Try / catch

try {
    return execute(sql);
} catch (SemanticException e) {
    if (e.getCode() == INVALID_PARAMETER_USAGE && e.getMessage().contains("requires a constant index")) {
        // rewrite to CASE over literal indices or extract in app code
    } else throw e;
}

Prevention

When it happens

Trigger: my_row[expr] where expr is not a literal, e.g. my_row[idx_col], my_row[1+1] as a non-literal AST node, or a parameterized index.

Common situations: Trying to iterate ROW fields with a loop variable, generated SQL using dynamic indices, porting array-style dynamic subscripting from other engines.

Related errors


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