{"record":{"id":"1fbcd850dc879672","repo":"apache/druid","slug":"cannot-implicitly-cast-s-to-s","errorCode":null,"errorMessage":"Cannot implicitly cast [%s] to [%s]","messagePattern":"Cannot implicitly cast \\[(.+?)\\] to \\[(.+?)\\]","errorType":"validation","errorClass":"Types.IncompatibleTypeException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/math/expr/ExpressionTypeConversion.java","lineNumber":104,"sourceCode":"  {\n    if (type == null) {\n      return other;\n    }\n    if (other == null) {\n      return type;\n    }\n    if (type.isArray() || other.isArray()) {\n      return leastRestrictiveType(type, other);\n    }\n    if (type.is(ExprType.COMPLEX) || other.is(ExprType.COMPLEX)) {\n      if (type.getComplexTypeName() == null) {\n        return other;\n      }\n      if (other.getComplexTypeName() == null) {\n        return type;\n      }\n      if (!Objects.equals(type, other)) {\n        throw new Types.IncompatibleTypeException(type, other);\n      }\n      return type;\n    }\n    // if both arguments are a string, type becomes a string\n    if (type.is(ExprType.STRING) && other.is(ExprType.STRING)) {\n      return ExpressionType.STRING;\n    }\n\n    // otherwise a decimal or integer number\n    return numeric(type, other);\n  }\n\n  /**\n   * Given 2 'input' types, choose the most appropriate combined type, if possible\n   *\n   * arrays must be the same type\n   * if either type is {@link ExprType#STRING}, the output type will be preserved as string\n   * if both types are {@link ExprType#LONG}, the output type will be preserved as long, otherwise","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/math/expr/ExpressionTypeConversion.java#L86-L122","documentation":"ExpressionTypeConversion.operator() computes the common type for the two operands of an expression operator. When either operand is a COMPLEX (non-nested-data) expression type, the two complex types must be identical; mixing two different complex types (e.g. two different extension complex types) in one operator is rejected with Types.IncompatibleTypeException, surfaced as 'Cannot implicitly cast [x] to [y]'.","triggerScenarios":"Using an arithmetic/comparison operator between two different COMPLEX expression types, e.g. expressions over two different complex columns (different complex type names) combined with +, -, *, ==, etc.","commonSituations":"Combining columns backed by different Druid extensions (e.g. two distinct sketch/complex serializers) in one expression; mistyping a column so a complex value is treated as numeric; writing native expressions in filters/select operators over complex columns.","solutions":["Don't apply operators directly to complex columns; extract a primitive first (e.g. use the extension's accessor/extractor functions to get a LONG/DOUBLE/STRING).","Ensure both operands resolve to the same complex type name, or cast one side appropriately.","Check the RowSignature typing — a mis-declared column type can make a plain value appear COMPLEX.","Catch Types.IncompatibleTypeException during query validation and return a clear 'cannot combine types' message to the user."],"exampleFix":"// before\n\"complexColA + complexColB\"\n// after\n\"extractValue(complexColA) + extractValue(complexColB)\" // extract primitives before operators","handlingStrategy":"validation","validationCode":"if (type != null && other != null && type.is(ExprType.COMPLEX) && other.is(ExprType.COMPLEX)\n    && !Objects.equals(type, other)) {\n  throw new IllegalStateException(\"Cannot combine complex types \" + type + \" and \" + other);\n}","typeGuard":"boolean operatorSafe(ExpressionType a, ExpressionType b) {\n  return !(a.is(ExprType.COMPLEX) && b.is(ExprType.COMPLEX) && !a.equals(b));\n}","tryCatchPattern":"try {\n  ExpressionType t = ExpressionTypeConversion.operator(a, b);\n} catch (Types.IncompatibleTypeException e) {\n  throw new QueryPlanningException(\"Operands have incompatible types: \" + e.getMessage());\n}","preventionTips":["Extract primitives from complex columns before applying operators","Never mix different complex extension types in one expression","Validate RowSignature types during query planning"],"tags":["druid","expressions","type-mismatch","complex-types"],"backgroundTag":"type-mismatch","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}