{"record":{"id":"3d3924e4529b7c95","repo":"prestodb/presto","slug":"type-mismatch-3d3924","errorCode":"TYPE_MISMATCH","errorMessage":"Types are not comparable with NULLIF: ${firstType} vs ${secondType}","messagePattern":"Types are not comparable with NULLIF: (.+?) vs (.+?)","errorType":"error_code","errorClass":"SemanticException","httpStatus":null,"severity":"error","filePath":"presto-main-base/src/main/java/com/facebook/presto/sql/relational/SqlToRowExpressionTranslator.java","lineNumber":939,"sourceCode":"        @Override\n        protected RowExpression visitNullIfExpression(NullIfExpression node, Context context)\n        {\n            RowExpression first = process(node.getFirst(), context);\n            RowExpression second = process(node.getSecond(), context);\n            Type returnType = getType(node);\n\n            if (!functionAndTypeManager.nullIfSpecialFormEnabled()) {\n                // If the first type is unknown, as per presto's NULL_IF semantics we should not infer the type using second argument.\n                // Always return a null with unknown type.\n                if (first.getType().equals(UnknownType.UNKNOWN)) {\n                    return constantNull(UnknownType.UNKNOWN);\n                }\n                RowExpression firstArgWithoutCast = first;\n\n                if (!second.getType().equals(first.getType())) {\n                    Optional<Type> commonType = functionAndTypeResolver.getCommonSuperType(first.getType(), second.getType());\n                    if (!commonType.isPresent()) {\n                        throw new SemanticException(TYPE_MISMATCH, node, \"Types are not comparable with NULLIF: %s vs %s\", first.getType(), second.getType());\n                    }\n\n                    // cast(first as <common type>)\n                    if (!first.getType().equals(commonType.get())) {\n                        first = call(\n                                getSourceLocation(node),\n                                CAST.name(),\n                                functionAndTypeResolver.lookupCast(CAST.name(), first.getType(), commonType.get()),\n                                commonType.get(), first);\n                    }\n                    // cast(second as <common type>)\n                    if (!second.getType().equals(commonType.get())) {\n                        second = call(\n                                getSourceLocation(node),\n                                CAST.name(),\n                                functionAndTypeResolver.lookupCast(CAST.name(), second.getType(), commonType.get()),\n                                commonType.get(), second);\n                    }","sourceCodeStart":921,"sourceCodeEnd":957,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main-base/src/main/java/com/facebook/presto/sql/relational/SqlToRowExpressionTranslator.java#L921-L957","documentation":"NULLIF requires its two argument types to be coercible to a common super type. When first and second argument types differ and functionAndTypeResolver.getCommonSuperType returns empty, the translator throws TYPE_MISMATCH because the values can never be meaningfully compared.","triggerScenarios":"Calling NULLIF(a, b) where a and b have unrelated types (e.g. a row/array/map type vs a scalar, or two types with no common super type) during expression analysis/translation.","commonSituations":"Comparing a struct/row with a primitive; comparing incompatible complex types after schema changes; dynamically generated SQL passing mismatched column types.","solutions":["Add an explicit CAST on one argument so both sides share a comparable type.","Change one of the arguments so types align (e.g. compare scalar fields of a row, not the row itself).","Fix upstream column definitions/schema so both expressions have the same type.","If types were recently changed in a migration, update dependent NULLIF expressions accordingly."],"exampleFix":"// before\nSELECT NULLIF(row_col, 1)\n// after\nSELECT NULLIF(row_col.field, 1)","handlingStrategy":"type-guard","validationCode":"// Ensure both sides of NULLIF resolve to the same type before building SQL\nif (!exprA.getType().equals(exprB.getType()) &&\n    !metadata.getFunctionAndTypeResolver().getCommonSuperType(exprA.getType(), exprB.getType()).isPresent()) {\n    throw new IllegalArgumentException(\"NULLIF args have no common supertype\");\n}","typeGuard":"boolean nullifComparable(Type a, Type b, FunctionAndTypeResolver r) {\n    return a.equals(b) || r.getCommonSuperType(a, b).isPresent();\n}","tryCatchPattern":"try {\n    session.execute(sql);\n} catch (SemanticException e) {\n    if (e.getCode() == SemanticErrorCode.TYPE_MISMATCH) {\n        // add explicit CASTs and retry\n    } else throw e;\n}","preventionTips":["Cast arguments to a common type explicitly before NULLIF","Compare scalar fields rather than whole ROW/complex types","Keep join/source column types aligned across schema migrations","Type-check dynamically generated expressions before execution"],"tags":["sql","type-mismatch","nullif","semantic-error"],"backgroundTag":"type-mismatch","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}