{"record":{"id":"df5cc504c185fcd3","repo":"prestodb/presto","slug":"invalid-function-argument-df5cc5","errorCode":"INVALID_FUNCTION_ARGUMENT","errorMessage":"Cannot unnest type: ","messagePattern":"Cannot unnest type: ","errorType":"error_code","errorClass":"PrestoException","httpStatus":null,"severity":"error","filePath":"presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java","lineNumber":1745,"sourceCode":"                }\n                Type expressionType = expressionAnalysis.getType(expression);\n                if (expressionType instanceof ArrayType) {\n                    Type elementType = ((ArrayType) expressionType).getElementType();\n                    if (!SystemSessionProperties.isLegacyUnnest(session) && elementType instanceof RowType) {\n                        ((RowType) elementType).getFields().stream()\n                                .map(field -> Field.newUnqualified(expression.getLocation(), field.getName(), field.getType()))\n                                .forEach(outputFields::add);\n                    }\n                    else {\n                        outputFields.add(Field.newUnqualified(expression.getLocation(), Optional.empty(), elementType));\n                    }\n                }\n                else if (expressionType instanceof MapType) {\n                    outputFields.add(Field.newUnqualified(expression.getLocation(), Optional.empty(), ((MapType) expressionType).getKeyType()));\n                    outputFields.add(Field.newUnqualified(expression.getLocation(), Optional.empty(), ((MapType) expressionType).getValueType()));\n                }\n                else {\n                    throw new PrestoException(StandardErrorCode.INVALID_FUNCTION_ARGUMENT, \"Cannot unnest type: \" + expressionType);\n                }\n\n                ImmutableList<Field> allFields = outputFields.build();\n                Set<SourceColumn> sourceColumns = analysis.getExpressionSourceColumns(expression);\n                for (int i = fieldsBefore; i < allFields.size(); i++) {\n                    analysis.addSourceColumns(allFields.get(i), sourceColumns);\n                }\n                fieldsBefore = allFields.size();\n            }\n            if (node.isWithOrdinality()) {\n                outputFields.add(Field.newUnqualified(node.getLocation(), Optional.empty(), BIGINT));\n            }\n            return createAndAssignScope(node, scope, outputFields.build());\n        }\n\n        @Override\n        protected Scope visitLateral(Lateral node, Optional<Scope> scope)\n        {","sourceCodeStart":1727,"sourceCodeEnd":1763,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java#L1727-L1763","documentation":"Presto throws a PrestoException with StandardErrorCode.INVALID_FUNCTION_ARGUMENT when an expression in an UNNEST clause has a type that is neither an ArrayType nor a MapType. UNNEST can only expand arrays (one output column of the element type) and maps (two output columns: key and value types); any other type cannot be unnested.","triggerScenarios":"Running `SELECT ... FROM t CROSS JOIN UNNEST(t.some_column) AS x(v)` where some_column is a row/varchar/int/etc. rather than ARRAY or MAP. The check happens in the analyzer after expression type inference: the final else branch throws.","commonSituations":"Schema changes turning an array column into a scalar/row type; misremembering a MAP column as an array (or vice versa) and destructuring it wrongly; connector type mapping producing ROW where the source was expected to be a list.","solutions":["Check the column's type with `DESCRIBE <table>` or `SELECT typeof(col) ...` and confirm it is ARRAY or MAP before unnesting.","Unnest the field of the ROW type instead, or access the array/map member: e.g. `UNNEST(t.row_field.array_field)`.","Cast or wrap the value: use `sequence()`/`split()`/`map_values()` etc. to produce an ARRAY from the actual data.","Catch PrestoException, check getErrorCode() == INVALID_FUNCTION_ARGUMENT and the 'Cannot unnest type:' prefix, and surface the offending type name to the user."],"exampleFix":"-- before (labels is VARCHAR)\nSELECT v FROM t CROSS JOIN UNNEST(t.labels) AS x(v)\n// after\nSELECT x.v FROM t CROSS JOIN UNNEST(split(t.labels, ',')) AS x(v)","handlingStrategy":"type-guard","validationCode":"try (ResultSet rs = stmt.executeQuery(\"SELECT typeof(col) FROM t LIMIT 1\")) {\n    String t = rs.getString(1).toLowerCase();\n    if (!t.startsWith(\"array\") && !t.startsWith(\"map\")) {\n        throw new IllegalArgumentException(\"cannot unnest type \" + t + \"; expected array or map\");\n    }\n}","typeGuard":"boolean isUnnestable(String prestoType) {\n    String t = prestoType == null ? \"\" : prestoType.toLowerCase();\n    return t.startsWith(\"array(\") || t.startsWith(\"map(\");\n}","tryCatchPattern":"try { runQuery(sql); } catch (PrestoException e) { if (e.getErrorCode() == StandardErrorCode.INVALID_FUNCTION_ARGUMENT.toErrorCodeCode() && e.getMessage().startsWith(\"Cannot unnest type:\")) { castOrRewrite(sql, e.getMessage()); } else { throw e; } }","preventionTips":["Run DESCRIBE table or typeof(col) before writing UNNEST queries against unfamiliar schemas.","Watch for schema migrations that change array columns to scalar or row types.","Unnest nested fields explicitly (row.array_field) rather than assuming the outer column is a container."],"tags":["sql","unnest","type-error","invalid-argument"],"backgroundTag":"cannot-unnest-type","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"}