{"record":{"id":"a22546ab45eaac88","repo":"apache/druid","slug":"validation-failure-on-row-d-s-vs-s","errorCode":null,"errorMessage":"Validation failure on row %d: [%s] vs [%s]","messagePattern":"Validation failure on row (.+?): \\[(.+?)\\] vs \\[(.+?)\\]","errorType":"validation","errorClass":"SegmentValidationException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/IndexIO.java","lineNumber":194,"sourceCode":"        final RowIterator it1 = adapter1.getRows();\n        final RowIterator it2 = adapter2.getRows()\n    ) {\n      long row = 0L;\n      while (it1.moveToNext()) {\n        if (!it2.moveToNext()) {\n          throw new SegmentValidationException(\"Unexpected end of second adapter\");\n        }\n        final RowPointer rp1 = it1.getPointer();\n        final RowPointer rp2 = it2.getPointer();\n        ++row;\n        if (rp1.getRowNum() != rp2.getRowNum()) {\n          throw new SegmentValidationException(\"Row number mismatch: [%d] vs [%d]\", rp1.getRowNum(), rp2.getRowNum());\n        }\n        try {\n          validateRowValues(rp1, adapter1, rp2, adapter2);\n        }\n        catch (SegmentValidationException ex) {\n          throw new SegmentValidationException(ex, \"Validation failure on row %d: [%s] vs [%s]\", row, rp1, rp2);\n        }\n      }\n      if (it2.moveToNext()) {\n        throw new SegmentValidationException(\"Unexpected end of first adapter\");\n      }\n      if (row != adapter1.getNumRows()) {\n        throw new SegmentValidationException(\n            \"Actual Row count mismatch. Expected [%d] found [%d]\",\n            row,\n            adapter1.getNumRows()\n        );\n      }\n    }\n  }\n\n  public QueryableIndex loadIndex(File inDir) throws IOException\n  {\n    return loadIndex(inDir, false, SegmentLazyLoadFailCallback.NOOP);","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/IndexIO.java#L176-L212","documentation":"When validateRowValues fails for a row pair inside validateTwoSegments, the caught SegmentValidationException is rethrown wrapped with row context: 'Validation failure on row %d: [%s] vs [%s]'. The original cause (e.g. dimension value or metric mismatch) is preserved as the exception cause.","triggerScenarios":"Any validateRowValues failure (dimension values, metric values, timestamps differing between adapters) for the row at position %d; the wrapper identifies which row and shows both row pointers.","commonSituations":"Data rewritten by a converter that altered values (e.g. lossy numeric conversion, changed string encoding); rollup/dedup differences between builds; null-handling changes across Druid versions in validated segments.","solutions":["Read the cause chain (getCause()) for the underlying validateRowValues error — the wrapper only locates the row.","Compare the printed row pointers' values to find which column differs.","Fix the converter/ingestion step that mutated the values and rebuild the segment.","If the diff is benign (e.g. formatting), update the validation tolerance or the reference segment."],"exampleFix":"// before: catching and losing context\ntry { io.validateTwoSegments(a, b); } catch (SegmentValidationException e) { log.error(e.getMessage()); }\n// after: surface the root cause and row\ntry { io.validateTwoSegments(a, b); } catch (SegmentValidationException e) {\n  log.error(e, \"Validation failed: %s | cause: %s\", e.getMessage(), e.getCause());\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  io.validateTwoSegments(adapter1, adapter2);\n} catch (SegmentValidationException e) {\n  Throwable cause = e.getCause();\n  log.error(\"Row-level validation failed: %s | root cause: %s\", e.getMessage(),\n      cause == null ? \"n/a\" : cause.getMessage());\n  throw e;\n}","preventionTips":["Always inspect getCause() — this message wraps the actual value mismatch.","Log both row pointers from the message to locate the differing column.","Validate value-preserving behavior of converters with unit tests on sample rows.","Watch for lossy conversions (float precision, encoding) when rewriting segments."],"tags":["segment-validation","row-values","wrapped-exception"],"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"}