apache/druid · error · SegmentValidationException

Dimension names differ. Expected

Error message

Dimension names differ. Expected [%s] found [%s]

What it means

During two-segment validation, IndexIO compares the sets of dimension names of both adapters. This SegmentValidationException is thrown when the dimension name sets differ, meaning one segment has dimensions the other lacks (or vice versa).

Solutions

  1. Diff the two dimension sets printed in the message to find the added/missing dimensions.
  2. Align ingestion specs (dimensionsList vs auto-discovery) so both segments carry the same schema.
  3. If the extra dimension is unintended, remove it from the input or spec and rebuild the segment.
  4. If dimensions were intentionally renamed, the segments are legitimately different — validate against the correct reference segment instead.

Example fix

// before: mismatched specs
spec1: {"dimensionsSpec":{"dimensions":["page","user"]}}
spec2: {"dimensionsSpec":{"dimensions":["page"]}}
// after: identical schemas
spec1: {"dimensionsSpec":{"dimensions":["page","user"]}}
spec2: {"dimensionsSpec":{"dimensions":["page","user"]}}
Defensive patterns

Strategy: validation

Validate before calling

Set<String> dims1 = Sets.newHashSet(adapter1.getDimensionNames(true));
Set<String> dims2 = Sets.newHashSet(adapter2.getDimensionNames(true));
if (!dims1.equals(dims2)) {
  System.out.println("Dim diff: only-1=" + Sets.difference(dims1, dims2)
      + " only-2=" + Sets.difference(dims2, dims1));
}

Try / catch

try {
  io.validateTwoSegments(adapter1, adapter2);
} catch (SegmentValidationException e) {
  if (e.getMessage().startsWith("Dimension names differ")) {
    log.error("Schema drift detected between segments: %s", e.getMessage());
  }
  throw e;
}

Prevention

When it happens

Trigger: validateTwoSegments with segments whose getDimensionNames(true) sets are unequal — e.g. one segment has an extra or missing dimension column.

Common situations: Schema drift between ingestion batches; auto-discovery of dimensions adding a field in only one segment; comparing a segment before/after a transform or dimension-exclusion change; upgrading with changed schema handling.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/segment/IndexIO.java:163

        );
      }
    }
  }

  public void validateTwoSegments(final IndexableAdapter adapter1, final IndexableAdapter adapter2)
  {
    if (adapter1.getNumRows() != adapter2.getNumRows()) {
      throw new SegmentValidationException(
          "Row count mismatch. Expected [%d] found [%d]",
          adapter1.getNumRows(),
          adapter2.getNumRows()
      );
    }
    {
      final Set<String> dimNames1 = Sets.newHashSet(adapter1.getDimensionNames(true));
      final Set<String> dimNames2 = Sets.newHashSet(adapter2.getDimensionNames(true));
      if (!dimNames1.equals(dimNames2)) {
        throw new SegmentValidationException(
            "Dimension names differ. Expected [%s] found [%s]",
            dimNames1,
            dimNames2
        );
      }
      final Set<String> metNames1 = Sets.newHashSet(adapter1.getMetricNames());
      final Set<String> metNames2 = Sets.newHashSet(adapter2.getMetricNames());
      if (!metNames1.equals(metNames2)) {
        throw new SegmentValidationException("Metric names differ. Expected [%s] found [%s]", metNames1, metNames2);
      }
    }
    try (
        final RowIterator it1 = adapter1.getRows();
        final RowIterator it2 = adapter2.getRows()
    ) {
      long row = 0L;
      while (it1.moveToNext()) {
        if (!it2.moveToNext()) {

View on GitHub (pinned to 9b90983fd2)