apache/druid · error · IllegalStateException

Cannot merge columns of type[%s] and format[%s] and with [%s

Error message

Cannot merge columns of type[%s] and format[%s] and with [%s] and [%s]

What it means

NestedCommonFormatColumn.merge() merges two shared dictionary/format definitions during nested-column serialization. It only succeeds when both sides have the same logical type and compatible format implementation classes; otherwise it throws an ISE because there is no defined way to combine the two column formats.

Source

Thrown at processing/src/main/java/org/apache/druid/segment/nested/NestedCommonFormatColumn.java:152

        final Format other = (Format) otherFormat;
        // when merging formats in the same ingestion job, all segments should have the exact same columnFormatSpec, so
        // no need to merge that
        if (!logicalType.equals(other.logicalType)) {
          return new Format(
              ColumnType.leastRestrictiveType(logicalType, other.logicalType),
              hasNulls || other.hasNulls,
              false,
              columnFormatSpec
          );
        }
        return new Format(
            logicalType,
            hasNulls || other.hasNulls,
            enforceLogicalType || other.enforceLogicalType,
            columnFormatSpec
        );
      }
      throw new ISE(
          "Cannot merge columns of type[%s] and format[%s] and with [%s] and [%s]",
          logicalType,
          this.getClass().getName(),
          otherFormat.getLogicalType(),
          otherFormat.getClass().getName()
      );
    }

    @Override
    public ColumnCapabilities toColumnCapabilities()
    {
      if (logicalType.isPrimitive() || logicalType.isArray()) {
        return ColumnCapabilitiesImpl.createDefault()
                                     .setType(logicalType)
                                     .setDictionaryEncoded(true)
                                     .setDictionaryValuesSorted(true)
                                     .setDictionaryValuesUnique(true)
                                     .setHasBitmapIndexes(true)

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Ensure the field's logical type is consistent across all input rows (use SQL CAST or an ingestion transform to normalize the type).
  2. Check ingestion spec for functions producing divergent types (e.g. expressions returning both string and numeric).
  3. Re-run the ingestion/compaction so both sides serialize with the same format version and implementation.
  4. Verify all tasks in a distributed ingestion run the same Druid version and identical column format configuration.

Example fix

// before: expression yields mixed types
// expr: "concat(\"x\", n)" sometimes STRING, sometimes LONG input
// after: force a single logical type in the ingestion spec
// "type": "long",
// "expr": "CAST(n AS LONG)"
Defensive patterns

Strategy: validation

Validate before calling

// ensure consistent logical type across inputs before merging/ingesting
if (!Objects.equals(thisFormat.getLogicalType(), otherFormat.getLogicalType())) {
  throw new IllegalArgumentException("Normalize field type before merge");
}

Type guard

boolean mergeable(NestedCommonFormatColumn a, NestedCommonFormatColumn b) {
  return a.getClass().equals(b.getClass()) &&
      Objects.equals(a.getLogicalType(), b.getLogicalType());
}

Try / catch

try {
  merged = format.merge(other);
} catch (IllegalStateException e) {
  if (e.getMessage().startsWith("Cannot merge columns of type")) {
    log.error(e, "Type/format mismatch while merging nested column");
  } else throw e;
}

Prevention

When it happens

Trigger: Writing/merging nested columns where two columns (or two parts of the same column) resolve to different logical types (e.g. LONG vs STRING) or different NestedCommonFormatColumn implementation classes.

Common situations: Schema drift during ingestion where the same field is sometimes a string and sometimes a number with incompatible coercions; merging partial dictionary state in compaction or task replication; mixing segment versions/formats.

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/b1fcae5ff0027899. Report an issue: GitHub.