{"record":{"id":"663d9507e96bb9f7","repo":"prestodb/presto","slug":"type-mismatch-663d95","errorCode":"TYPE_MISMATCH","errorMessage":"Cannot cast type %s to %s","messagePattern":"Cannot cast type (.+?) to (.+?)","errorType":"error_code","errorClass":"SemanticException","httpStatus":null,"severity":"error","filePath":"presto-main-base/src/main/java/com/facebook/presto/sql/planner/ExpressionInterpreter.java","lineNumber":202,"sourceCode":"    }\n\n    public static ExpressionInterpreter expressionOptimizer(Expression expression, Metadata metadata, Session session, Map<NodeRef<Expression>, Type> expressionTypes)\n    {\n        requireNonNull(expression, \"expression is null\");\n        requireNonNull(metadata, \"metadata is null\");\n        requireNonNull(session, \"session is null\");\n\n        return new ExpressionInterpreter(expression, metadata, session, expressionTypes, true);\n    }\n\n    public static Object evaluateConstantExpression(Expression expression, Type expectedType, Metadata metadata, Session session, Map<NodeRef<Parameter>, Expression> parameters)\n    {\n        ExpressionAnalyzer analyzer = createConstantAnalyzer(metadata.getFunctionAndTypeManager().getFunctionAndTypeResolver(), session, parameters, WarningCollector.NOOP);\n        analyzer.analyze(expression, Scope.create());\n\n        Type actualType = analyzer.getExpressionTypes().get(NodeRef.of(expression));\n        if (!metadata.getFunctionAndTypeManager().canCoerce(actualType, expectedType)) {\n            throw new SemanticException(SemanticErrorCode.TYPE_MISMATCH, expression, format(\"Cannot cast type %s to %s\",\n                    actualType.getTypeSignature(),\n                    expectedType.getTypeSignature()));\n        }\n\n        Map<NodeRef<Expression>, Type> coercions = ImmutableMap.<NodeRef<Expression>, Type>builder()\n                .putAll(analyzer.getExpressionCoercions())\n                .put(NodeRef.of(expression), expectedType)\n                .build();\n        return evaluateConstantExpression(expression, coercions, analyzer.getTypeOnlyCoercions(), metadata, session, ImmutableSet.of(), parameters);\n    }\n\n    private static Object evaluateConstantExpression(\n            Expression expression,\n            Map<NodeRef<Expression>, Type> coercions,\n            Set<NodeRef<Expression>> typeOnlyCoercions,\n            Metadata metadata,\n            Session session,\n            Set<NodeRef<Expression>> columnReferences,","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main-base/src/main/java/com/facebook/presto/sql/planner/ExpressionInterpreter.java#L184-L220","documentation":"When evaluating a constant expression (e.g. for partition pruning or dynamic filtering), Presto analyzes the expression and checks that its actual type can coerce to the expected type. If FunctionAndTypeManager.canCoerce fails, it throws TYPE_MISMATCH 'Cannot cast type X to Y'. This guards constant-expression evaluation against type inconsistencies between planner expectations and expression analysis.","triggerScenarios":"Pushdown of predicates/partition filters where the literal's analyzed type cannot be coerced to the column type (e.g. passing a varchar where an interval is expected, or incompatible struct shapes).","commonSituations":"Connector pushdown code supplying a wrong expectedType; queries with literals typed incompatibly against partition columns; custom connector filter translation bugs; changes to type coercion rules after an upgrade.","solutions":["Fix the query's literal/expression to match the target column type (e.g. use explicit CAST)","Check the connector/pushdown code to ensure expectedType matches the actual column type metadata","Upgrade Presto if a previously working predicate now fails due to coercion rule changes"],"exampleFix":"// before (connector pushdown)\nTupleDomain<ColumnHandle> domain = ...; // expectedType = BIGINT for a VARCHAR column\n// after\nType expectedType = columnHandle.getType(); // derive from actual column metadata\nif (!metadata.canCoerce(actualType, expectedType)) { skip pushdown; }","handlingStrategy":"validation","validationCode":"// Check coercibility before constant-expression pushdown\nType actual = analyzer.getExpressionTypes().get(NodeRef.of(expression));\nif (!metadata.getFunctionAndTypeManager().canCoerce(actual, expectedType)) {\n    // skip pushdown or CAST the expression first\n}","typeGuard":"boolean canPushConstant(Metadata metadata, Type actualType, Type expectedType) {\n    return metadata.getFunctionAndTypeManager().canCoerce(actualType, expectedType);\n}","tryCatchPattern":"try { result = expressionInterpreter.evaluateConstantExpression(expr, expectedType, ...); } catch (SemanticException e) { if (e.getCode().equals(TYPE_MISMATCH) && e.getMessage().startsWith(\"Cannot cast type\")) { skipPushdown(); } else throw e; }","preventionTips":["Ensure expectedType always comes from real column metadata, not hardcoded types","Use explicit CAST in queries when literal types may differ from column types","When building connectors, derive pushdown types from the declared column handles","Retest predicate pushdown after Presto upgrades, as coercion rules can change"],"tags":["sql","type-system","expression-evaluation"],"backgroundTag":"type-cast-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"}