{"record":{"id":"9c6da1f3b699433a","repo":"apache/druid","slug":"cannot-merge-columns-of-type-s-and-format-s-an","errorCode":null,"errorMessage":"Cannot merge columns of type[%s] and format[%s] and with [%s] and [%s]","messagePattern":"Cannot merge columns of type\\[(.+?)\\] and format\\[(.+?)\\] and with \\[(.+?)\\] and \\[(.+?)\\]","errorType":"exception","errorClass":"ISE","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/column/StringDictionaryEncodedColumnFormat.java","lineNumber":142,"sourceCode":"      if (!otherCaps.is(ValueType.STRING)) {\n        throw new ISE(\n            \"Cannot merge columns of type[%s] and format[%s] with type[%s] and format[%s]\",\n            ColumnType.STRING,\n            this.getClass().getName(),\n            otherFormat.getLogicalType(),\n            otherFormat.getClass().getName()\n        );\n      }\n      return new StringDictionaryEncodedColumnFormat(\n          hasMultipleValues || otherCaps.hasMultipleValues().isMaybeTrue(),\n          hasNulls || otherCaps.hasNulls().isMaybeTrue(),\n          hasBitmapIndexes && otherCaps.hasBitmapIndexes(),\n          hasSpatialIndexes || otherCaps.hasSpatialIndexes(),\n          columnFormatSpec\n      );\n    }\n\n    throw new ISE(\n        \"Cannot merge columns of type[%s] and format[%s] and with [%s] and [%s]\",\n        ColumnType.STRING,\n        this.getClass().getName(),\n        otherFormat.getLogicalType(),\n        otherFormat.getClass().getName()\n    );\n  }\n}\n","sourceCodeStart":124,"sourceCodeEnd":151,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/column/StringDictionaryEncodedColumnFormat.java#L124-L151","documentation":"StringDictionaryEncodedColumnFormat.merge() falls through to this ISE when the other format is neither a CapabilitiesBasedFormat nor a compatible mergeable format — i.e. two string-typed formats whose concrete format classes cannot be merged (for example legacy formats or unknown format implementations mixed in one merge job). Raised via combine/aggregate during segment merging.","triggerScenarios":"Calling merge() with an otherFormat that is not a CapabilitiesBasedFormat and not mergeable with this StringDictionaryEncodedColumnFormat implementation — e.g. a custom/foreign ColumnFormatSpec or a legacy format class in the same merge.","commonSituations":"Compaction/merge jobs spanning segments written by different Druid versions or different format specifications (e.g. one with dictionary encoding version X, another with an incompatible or custom format); rolling upgrades with mixed segment format versions.","solutions":["Reindex/compact the segments to a single common format before merging (druid.compaction.* or re-index task)","Ensure all nodes in the merge path run compatible Druid versions","Check for custom ColumnFormat implementations that don't support merge and implement merge() for them"],"exampleFix":"// before\n// merging segments with legacy string column format and new dictionary-encoded format directly\n// after\n// run a re-index task to normalize formats first:\n// ioConfig: { \"type\": \"index_parallel\", \"inputSource\": { \"type\": \"druid\", \"dataSource\": \"src\", \"interval\": \"...\" } }\n// which rewrites all segments to the current dictionary-encoded format before merging","handlingStrategy":"validation","validationCode":"if (!(otherFormat instanceof CapabilitiesBasedFormat) && !otherFormat.getClass().equals(this.getClass())) {\n  throw new IllegalStateException(\"Incompatible column formats for merge: \" + otherFormat.getClass().getName());\n}","typeGuard":"boolean isMergeableWith(ColumnFormat self, ColumnFormat other) {\n  return other instanceof CapabilitiesBasedFormat || other.getClass().equals(self.getClass());\n}","tryCatchPattern":"try {\n  ColumnFormat merged = self.merge(otherFormat, caps);\n} catch (ISE e) {\n  // fall back to re-indexing the segments into a common format\n  submitReindexTask(segments);\n}","preventionTips":["Upgrade all nodes before merging segments written by different versions","Normalize legacy segments to the current format via re-index before compaction","Avoid custom ColumnFormat implementations unless merge() is properly implemented"],"tags":["java","segment-merge","column-format","incompatible-format"],"backgroundTag":"incompatible-source-type","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}