apache/druid · error · SegmentValidationException
Dim [ ] types not equal. Expected found
Error message
Dim [%s] types not equal. Expected %d found %d
What it means
validateRowValues compares column capabilities of each dimension pair across the two segments. The message text mistakenly formats ColumnType objects with %d, but the failure means the two segments declare different column types (e.g. STRING vs LONG) for the same dimension. Such segments are not equivalent and validation aborts.
Solutions
- Fix the ingestion spec to declare the same explicit dimension type for both segments and re-ingest
- Re-persist one segment with dimension conversion (IndexMerger convert) to match the other's column type
- Verify with SegmentMetadataQuery which column types differ before validating
Example fix
// before (ingest spec, inconsistent typing)
"dimensions": ["page"]
// after
"dimensions": [{"type": "string", "name": "page"}]
// keep identical declarations in both ingestion specs Defensive patterns
Strategy: validation
Validate before calling
for (String dim : dims) {
ColumnType t1 = adapter1.getCapabilities(dim).toColumnType();
ColumnType t2 = adapter2.getCapabilities(dim).toColumnType();
if (!Objects.equals(t1, t2)) {
throw new IllegalStateException("Type mismatch on dim " + dim + ": " + t1 + " vs " + t2);
}
} Try / catch
try {
IndexIO.validateTwoSegments(adapter1, adapter2);
} catch (SegmentValidationException e) {
if (e.getMessage().contains("types not equal")) {
// convert one segment's column type before retrying
}
} Prevention
- Declare explicit dimension types in ingestion specs to avoid auto-detection drift
- Compare column capabilities with a SegmentMetadataQuery before merging/validating
When it happens
Trigger: IndexIO.validateTwoSegments on segments where adapter.getCapabilities(dimName).toColumnType() differs for a shared dimension — one segment auto-typed a dimension as numeric while the other kept it as string.
Common situations: Re-ingestion with different auto-detection results (numbers parsed as strings in one run); schema drift after changing ingest spec dimension type declarations; validating segments from different Druid versions with different typing rules.
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
- Actual Row count mismatch. Expected
- Aggregation [ ] does not support column [ ] of type [ ]…
- Dim lengths not equal
- at least 2 bins expected
- at least 2 bins expected
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/b51cffd33a5ed962.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/segment/IndexIO.java:272
}
final List<Object> dims1 = rp1.getDimensionValuesForDebug();
final List<Object> dims2 = rp2.getDimensionValuesForDebug();
if (dims1.size() != dims2.size()) {
throw new SegmentValidationException("Dim lengths not equal %s vs %s", dims1, dims2);
}
final List<String> dim1Names = adapter1.getDimensionNames(false);
final List<String> dim2Names = adapter2.getDimensionNames(false);
int dimCount = dims1.size();
for (int i = 0; i < dimCount; ++i) {
final String dim1Name = dim1Names.get(i);
final String dim2Name = dim2Names.get(i);
ColumnCapabilities capabilities1 = adapter1.getCapabilities(dim1Name);
ColumnCapabilities capabilities2 = adapter2.getCapabilities(dim2Name);
ColumnType dim1Type = capabilities1.toColumnType();
ColumnType dim2Type = capabilities2.toColumnType();
if (!Objects.equals(dim1Type, dim2Type)) {
throw new SegmentValidationException(
"Dim [%s] types not equal. Expected %d found %d",
dim1Name,
dim1Type,
dim2Type
);
}
Object vals1 = dims1.get(i);
Object vals2 = dims2.get(i);
if (isNullRow(vals1) ^ isNullRow(vals2)) {
throw notEqualValidationException(dim1Name, vals1, vals2);
}
boolean vals1IsList = vals1 instanceof List;
boolean vals2IsList = vals2 instanceof List;
if (vals1IsList ^ vals2IsList) {
if (vals1IsList) {
if (((List) vals1).size() != 1 || !Objects.equals(((List) vals1).get(0), vals2)) {
throw notEqualValidationException(dim1Name, vals1, vals2);View on GitHub (pinned to 9b90983fd2)