{"record":{"id":"9569adb2029a13ee","repo":"prestodb/presto","slug":"invalid-parameter-usage-9569ad","errorCode":"INVALID_PARAMETER_USAGE","errorMessage":"Subscript expression on ROW requires a constant index","messagePattern":"Subscript expression on ROW requires a constant index","errorType":"error_code","errorClass":"SemanticException","httpStatus":null,"severity":"error","filePath":"presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/ExpressionAnalyzer.java","lineNumber":808,"sourceCode":"        }\n\n        private Type getVarcharType(Expression value, StackableAstVisitorContext<Context> context)\n        {\n            Type type = process(value, context);\n            if (!(type instanceof VarcharType)) {\n                return VARCHAR;\n            }\n            return type;\n        }\n\n        @Override\n        protected Type visitSubscriptExpression(SubscriptExpression node, StackableAstVisitorContext<Context> context)\n        {\n            Type baseType = process(node.getBase(), context);\n            // Subscript on Row hasn't got a dedicated operator. Its Type is resolved by hand.\n            if (baseType instanceof RowType) {\n                if (!(node.getIndex() instanceof LongLiteral)) {\n                    throw new SemanticException(\n                            INVALID_PARAMETER_USAGE,\n                            node.getIndex(),\n                            \"Subscript expression on ROW requires a constant index\");\n                }\n                Type indexType = process(node.getIndex(), context);\n                if (!indexType.equals(INTEGER)) {\n                    throw new SemanticException(\n                            TYPE_MISMATCH,\n                            node.getIndex(),\n                            \"Subscript expression on ROW requires integer index, found %s\", indexType);\n                }\n                int indexValue = toIntExact(((LongLiteral) node.getIndex()).getValue());\n                if (indexValue <= 0) {\n                    throw new SemanticException(\n                            INVALID_PARAMETER_USAGE,\n                            node.getIndex(),\n                            \"Invalid subscript index: %s. ROW indices start at 1\", indexValue);\n                }","sourceCodeStart":790,"sourceCodeEnd":826,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/ExpressionAnalyzer.java#L790-L826","documentation":"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.","triggerScenarios":"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.","commonSituations":"Trying to iterate ROW fields with a loop variable, generated SQL using dynamic indices, porting array-style dynamic subscripting from other engines.","solutions":["Use a literal integer index, e.g. my_row[1]","If dynamic access is needed, convert the ROW to a map or use a CASE expression over literal indices","Extract the field in application code instead of SQL"],"exampleFix":"// before\nSELECT my_row[idx] FROM t\n// after\nSELECT CASE idx WHEN 1 THEN my_row[1] WHEN 2 THEN my_row[2] END FROM t","handlingStrategy":"validation","validationCode":"if (isRowType(baseType) && !(indexExpr instanceof LongLiteral)) {\n    throw new IllegalArgumentException(\"ROW subscript requires a constant integer literal\");\n}","typeGuard":"boolean isConstantRowIndex(Expression index) { return index instanceof LongLiteral; }","tryCatchPattern":"try {\n    return execute(sql);\n} catch (SemanticException e) {\n    if (e.getCode() == INVALID_PARAMETER_USAGE && e.getMessage().contains(\"requires a constant index\")) {\n        // rewrite to CASE over literal indices or extract in app code\n    } else throw e;\n}","preventionTips":["Only use literal integer indices on ROW values","Convert ROWs to MAPs when dynamic key access is required","Do dynamic field selection in application code, not SQL","Lint generated SQL for non-literal subscripts on ROW-typed columns"],"tags":["sql","row-type","subscript"],"backgroundTag":"non-constant-index","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"}