{"record":{"id":"252a2c77d2eec793","repo":"prestodb/presto","slug":"table-function-invalid-column-reference","errorCode":"TABLE_FUNCTION_INVALID_COLUMN_REFERENCE","errorMessage":"Expected column reference. Actual: %s","messagePattern":"Expected column reference\\. Actual: (.+?)","errorType":"error_code","errorClass":"SemanticException","httpStatus":null,"severity":"error","filePath":"presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java","lineNumber":2226,"sourceCode":"                                                        }\n                                                    })))\n                                            .collect(toImmutableList())))\n                                    .build())\n                            .orElse(NULL_DESCRIPTOR),\n                    Optional.empty());\n        }\n\n        private Field validateAndGetInputField(Expression expression, Scope inputScope)\n        {\n            QualifiedName qualifiedName;\n            if (expression instanceof Identifier) {\n                qualifiedName = QualifiedName.of(ImmutableList.of(((Identifier) expression)));\n            }\n            else if (expression instanceof DereferenceExpression) {\n                qualifiedName = getQualifiedName((DereferenceExpression) expression);\n            }\n            else {\n                throw new SemanticException(TABLE_FUNCTION_INVALID_COLUMN_REFERENCE, expression, \"Expected column reference. Actual: %s\", expression);\n            }\n            Optional<ResolvedField> field = inputScope.tryResolveField(expression, qualifiedName);\n            if (!field.isPresent() || !field.get().isLocal()) {\n                throw new SemanticException(TABLE_FUNCTION_COLUMN_NOT_FOUND, expression, \"Column %s is not present in the input relation\", expression);\n            }\n\n            return field.get().getField();\n        }\n\n        private List<List<String>> analyzeCopartitioning(List<List<QualifiedName>> copartitioning, List<TableArgumentAnalysis> tableArgumentAnalyses)\n        {\n            // map table arguments by relation names. usa a multimap, because multiple arguments can have the same value, e.g. input_1 => tpch.tiny.orders, input_2 => tpch.tiny.orders\n            ImmutableMultimap.Builder<QualifiedName, TableArgumentAnalysis> unqualifiedInputsBuilder = ImmutableMultimap.builder();\n            ImmutableMultimap.Builder<QualifiedName, TableArgumentAnalysis> qualifiedInputsBuilder = ImmutableMultimap.builder();\n            tableArgumentAnalyses.stream()\n                    .filter(argument -> argument.getName().isPresent())\n                    .forEach(argument -> {\n                        QualifiedName name = argument.getName().get();","sourceCodeStart":2208,"sourceCodeEnd":2244,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java#L2208-L2244","documentation":"A table function argument expected a column reference — an Identifier or DereferenceExpression such as t.col — but received some other expression. validateAndGetInputField in StatementAnalyzer only handles these two node types for resolving input columns and throws TABLE_FUNCTION_INVALID_COLUMN_REFERENCE otherwise.","triggerScenarios":"Passing an arbitrary expression into a table argument's column-reference slot, e.g. PASSING t.a + 1 AS x, a function call, a CASE expression, or a literal where a plain column is required.","commonSituations":"Trying to compute derived columns inside table function arguments; wrapping column names in expressions or functions like lower(col).","solutions":["Pass a bare column reference: identifier or table.column form.","Compute derived values in a subquery/CTE first, then pass the projected column.","Use DESCRIPTOR(...) if the parameter expects column descriptors, not expressions."],"exampleFix":"// before\nTABLE(fn(input => (SELECT a + 1 AS b FROM t), col => b + 1))\n\n// after\nWITH prepared AS (SELECT a + 1 AS b FROM t)\nSELECT * FROM TABLE(fn(input => prepared, col => b))","handlingStrategy":"validation","validationCode":"// Only pass plain column references (identifier or table.column) to table-function slots\nPattern COL_REF = Pattern.compile(\"[A-Za-z_][A-Za-z0-9_]*(\\\\.[A-Za-z_][A-Za-z0-9_]*)*\");\nif (!COL_REF.matcher(argExpr.trim()).matches()) {\n    throw new IllegalArgumentException(\"Expected column reference, got expression: \" + argExpr);\n}","typeGuard":"boolean isColumnReference(String expr) {\n    return expr != null && expr.trim().matches(\"[A-Za-z_][A-Za-z0-9_]*(\\\\.[A-Za-z_][A-Za-z0-9_]*)*\");\n}","tryCatchPattern":null,"preventionTips":["Never pass computed expressions where the function expects a column.","Pre-compute derived values in a CTE/subquery and pass the projected column.","Use DESCRIPTOR when the parameter expects a schema, not a single column."],"tags":["sql","table-functions","column-reference"],"backgroundTag":"expected-column-reference","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"}