{"record":{"id":"5a046baf5cb8602f","repo":"apache/druid","slug":"row-count-mismatch-expected-d-found-d","errorCode":null,"errorMessage":"Row count mismatch. Expected [%d] found [%d]","messagePattern":"Row count mismatch\\. Expected \\[(.+?)\\] found \\[(.+?)\\]","errorType":"validation","errorClass":"SegmentValidationException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/IndexIO.java","lineNumber":153,"sourceCode":"    indexLoaders = indexLoadersBuilder.build();\n  }\n\n  public void validateTwoSegments(File dir1, File dir2) throws IOException\n  {\n    try (QueryableIndex queryableIndex1 = loadIndex(dir1)) {\n      try (QueryableIndex queryableIndex2 = loadIndex(dir2)) {\n        validateTwoSegments(\n            new QueryableIndexIndexableAdapter(queryableIndex1),\n            new QueryableIndexIndexableAdapter(queryableIndex2)\n        );\n      }\n    }\n  }\n\n  public void validateTwoSegments(final IndexableAdapter adapter1, final IndexableAdapter adapter2)\n  {\n    if (adapter1.getNumRows() != adapter2.getNumRows()) {\n      throw new SegmentValidationException(\n          \"Row count mismatch. Expected [%d] found [%d]\",\n          adapter1.getNumRows(),\n          adapter2.getNumRows()\n      );\n    }\n    {\n      final Set<String> dimNames1 = Sets.newHashSet(adapter1.getDimensionNames(true));\n      final Set<String> dimNames2 = Sets.newHashSet(adapter2.getDimensionNames(true));\n      if (!dimNames1.equals(dimNames2)) {\n        throw new SegmentValidationException(\n            \"Dimension names differ. Expected [%s] found [%s]\",\n            dimNames1,\n            dimNames2\n        );\n      }\n      final Set<String> metNames1 = Sets.newHashSet(adapter1.getMetricNames());\n      final Set<String> metNames2 = Sets.newHashSet(adapter2.getMetricNames());\n      if (!metNames1.equals(metNames2)) {","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/IndexIO.java#L135-L171","documentation":"IndexIO.validateTwoSegments compares two segment adapters for equivalence. Before comparing rows, it first asserts both adapters report the same numRows; otherwise row-by-row comparison is meaningless. This SegmentValidationException fires when the two segments' row counts differ.","triggerScenarios":"Calling IndexIO.validateTwoSegments(adapter1, adapter2) (or the File-based overload) with two segments where adapter1.getNumRows() != adapter2.getNumRows(), typically when validating a converted/rewritten segment against its source.","commonSituations":"Reindexing or compaction jobs that dropped or duplicated rows; comparing a shard produced by a new Druid version against the original; segment conversion tools (converter/merger) with bugs; comparing segments built from different input slices.","solutions":["Check the two numbers in the message: determine which segment is missing/extra rows and inspect its input or conversion job logs.","Re-run ingestion/conversion for the faulty segment after fixing the discrepancy.","Ensure both segments were built from the same input data and time chunk before validating.","If validating after a Druid upgrade, confirm row-count-affecting behavior changes (e.g. dedup, rollup settings) match between the two builds."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (adapter1.getNumRows() != adapter2.getNumRows()) {\n  throw new IllegalStateException(\"Skip validateTwoSegments: row counts differ: \"\n      + adapter1.getNumRows() + \" vs \" + adapter2.getNumRows());\n}\nio.validateTwoSegments(adapter1, adapter2);","typeGuard":null,"tryCatchPattern":"try {\n  io.validateTwoSegments(adapter1, adapter2);\n} catch (SegmentValidationException e) {\n  log.error(\"Segment validation failed: %s\", e.getMessage());\n  // quarantine the segment, do not publish\n}","preventionTips":["Validate segments only against replicas/rewrites built from identical input.","Check row counts yourself before invoking row-level comparison for clearer diagnostics.","Pin ingestion specs (rollup, dimensions) when generating segments intended to be equivalent.","Re-run validation after any Druid version change that affects segment building."],"tags":["segment-validation","segments","indexio"],"backgroundTag":"schema-validation-failed","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"}