apache/druid · error · IncompatibleTypeException

Incompatible types: %s and %s

Error message

Incompatible types: %s and %s

What it means

ColumnType.leastRestrictiveType computes the common supertype of two column types; when neither is null and neither is nested-data-compatible complex, incompatible types (e.g. STRING vs LONG) raise Types.IncompatibleTypeException. It is thrown while reconciling types across operators, functions, or auto-detected inputs.

Source

Thrown at processing/src/main/java/org/apache/druid/segment/column/ColumnType.java:178

   */
  @Nullable
  public static ColumnType leastRestrictiveType(@Nullable ColumnType type, @Nullable ColumnType other) throws Types.IncompatibleTypeException
  {
    if (type == null) {
      return other;
    }
    if (other == null) {
      return type;
    }
    if (type.is(ValueType.COMPLEX) && other.is(ValueType.COMPLEX)) {
      if (type.getComplexTypeName() == null) {
        return other;
      }
      if (other.getComplexTypeName() == null) {
        return type;
      }
      if (!Objects.equals(type, other)) {
        throw new Types.IncompatibleTypeException(type, other);
      }
      return type;
    }
    // if either is nested data, use nested data, otherwise error
    if (type.is(ValueType.COMPLEX) || other.is(ValueType.COMPLEX)) {
      if (ColumnType.NESTED_DATA.equals(type) || ColumnType.NESTED_DATA.equals(other)) {
        return ColumnType.NESTED_DATA;
      }
      throw new Types.IncompatibleTypeException(type, other);
    }

    // arrays convert based on least restrictive element type
    if (type.isArray()) {
      if (other.equals(type.getElementType())) {
        return type;
      }
      final ColumnType commonElementType;
      // commonElementType cannot be null if we got this far, we always return a value unless both args are null

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Add explicit CASTs so both sides share a type: CAST(col AS BIGINT) or CAST(col AS VARCHAR)
  2. Fix the schema/type of one input column (re-index or correct ingestion type)
  3. If a complex (COMPLEX<name>) column is involved, ensure both sides use the same complex type name or cast to a primitive

Example fix

// before
// WHERE stringCol = longCol  -> Incompatible types: STRING and LONG
// after
// WHERE stringCol = CAST(longCol AS VARCHAR)
Defensive patterns

Strategy: validation

Validate before calling

ColumnType a = sqlTypeNameOf(left), b = sqlTypeNameOf(right);
try { ColumnType.common = ColumnType.leastRestrictiveType(a, b); } catch (IncompatibleTypeException e) { /* require explicit CAST */ }

Try / catch

try { common = ColumnType.leastRestrictiveType(t1, t2); } catch (IncompatibleTypeException e) { throw new ValidationException("add a CAST between " + t1 + " and " + t2); }

Prevention

When it happens

Trigger: leastRestrictiveType(string, long) or similar, invoked from autoDetect, operator/function type resolution, or recursive calls, when no common supertype exists.

Common situations: SQL queries joining/comparing columns of incompatible types (string vs number, different complex types); COALESCE/CASE branches with mismatched types; schema drift between tables in a join.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/f0db2a00d48291f8. Report an issue: GitHub.