{"record":{"id":"0c5c9fc4fd059349","repo":"prestodb/presto","slug":"type-mismatch-0c5c9f","errorCode":"TYPE_MISMATCH","errorMessage":"Expression %s is not of type ROW","messagePattern":"Expression (.+?) is not of type ROW","errorType":"error_code","errorClass":"SemanticException","httpStatus":null,"severity":"error","filePath":"presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/ExpressionAnalyzer.java","lineNumber":589,"sourceCode":"                    }\n                    if (outerScopeSymbolTypes.containsKey(NodeRef.of(node))) {\n                        return setExpressionType(node, outerScopeSymbolTypes.get(NodeRef.of(node)));\n                    }\n                    throw missingAttributeException(node, qualifiedName);\n                }\n            }\n\n            Type baseType = process(node.getBase(), context);\n            addColumnSubfieldReferences(node, context);\n\n            if (((baseType instanceof TypeWithName) && ((TypeWithName) baseType).getType() instanceof RowType)) {\n                baseType = ((TypeWithName) baseType).getType();\n            }\n            if (baseType instanceof DistinctType) {\n                baseType = ((DistinctType) baseType).getBaseType();\n            }\n            if (!(baseType instanceof RowType)) {\n                throw new SemanticException(TYPE_MISMATCH, node.getBase(), \"Expression %s is not of type ROW\", node.getBase());\n            }\n\n            RowType rowType = (RowType) baseType;\n            String fieldName = node.getField().getValue();\n\n            Type rowFieldType = null;\n            for (RowType.Field rowField : rowType.getFields()) {\n                if (fieldName.equalsIgnoreCase(rowField.getName().orElse(null))) {\n                    rowFieldType = rowField.getType();\n                    break;\n                }\n            }\n\n            if (sqlFunctionProperties.isLegacyRowFieldOrdinalAccessEnabled() && rowFieldType == null) {\n                OptionalInt rowIndex = parseAnonymousRowFieldOrdinalAccess(fieldName, rowType.getFields());\n                if (rowIndex.isPresent()) {\n                    rowFieldType = rowType.getFields().get(rowIndex.getAsInt()).getType();\n                }","sourceCodeStart":571,"sourceCodeEnd":607,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/ExpressionAnalyzer.java#L571-L607","documentation":"A dereference expression (base.field) requires the base expression to be of ROW type (after unwrapping TypeWithName and DistinctType). If the resolved base type is anything else, the analyzer throws TYPE_MISMATCH pointing at the base expression.","triggerScenarios":"Using dot-notation field access on a non-ROW value, e.g. my_map.key where my_map is MAP, or col.field where col is VARCHAR/ARRAY.","commonSituations":"Confusing map access with row field access (SQL maps use [] not dot), dereferencing a column whose type changed after a schema change, accessing fields of a NULL-typed or unknown expression.","solutions":["Verify the base expression's type is ROW; cast it if needed","Use subscript syntax for maps/arrays instead of dot access","Fix upstream schema/type so the column is actually a ROW"],"exampleFix":"// before\nSELECT my_map.key FROM t\n// after\nSELECT my_map['key'] FROM t","handlingStrategy":"type-guard","validationCode":"Type baseType = expressionAnalyzer.getType(baseExpr);\nif (!(unwrap(baseType) instanceof RowType)) {\n    throw new IllegalArgumentException(\"Base of field access must be ROW, got \" + baseType);\n}","typeGuard":"boolean isRowAccess(Expression base, FunctionAndTypeManager types) {\n    Type t = types.getType(base);\n    while (t instanceof TypeWithName) t = ((TypeWithName) t).getType();\n    return t instanceof RowType;\n}","tryCatchPattern":"try {\n    return execute(sql);\n} catch (SemanticException e) {\n    if (e.getCode() == TYPE_MISMATCH && e.getMessage().contains(\"is not of type ROW\")) {\n        // suggest map subscript or cast, or report type of offending base\n    } else throw e;\n}","preventionTips":["Use ['key'] subscripting for MAPs, dot access only for ROWs","Check column types in metadata before generating dereference expressions","Re-validate dereference expressions after schema changes","Unwrap DistinctType when reasoning about field access in tooling"],"tags":["sql","type-mismatch","row-type"],"backgroundTag":"type-mismatch","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"}