prestodb/presto · error · OrcCorruptionException

Unexpected row group %s in stripe at offset %s

Error message

Unexpected row group %s in stripe at offset %s

What it means

Write validation compares per-row-group statistics recorded at write time to those read back. The recorded stripe has fewer row groups than the row group index requested, so the reader cannot validate that row group and treats the file as corrupt.

Source

Thrown at presto-orc/src/main/java/com/facebook/presto/orc/OrcWriteValidation.java:447

                stack.addAll(orcType.getFieldTypeIndexes());
            }
        }
        return valueNodes.build();
    }

    public void validateRowGroupStatistics(
            OrcDataSourceId orcDataSourceId,
            long stripeOffset,
            int rowGroupIndex,
            List<ColumnStatistics> actual)
            throws OrcCorruptionException
    {
        List<RowGroupStatistics> rowGroups = rowGroupStatistics.get(stripeOffset);
        if (rowGroups == null) {
            throw new OrcCorruptionException(orcDataSourceId, "Unexpected stripe at offset %s", stripeOffset);
        }
        if (rowGroups.size() <= rowGroupIndex) {
            throw new OrcCorruptionException(orcDataSourceId, "Unexpected row group %s in stripe at offset %s", rowGroupIndex, stripeOffset);
        }

        // exclude stats for flat map keys because they are not present in the row group stats
        ImmutableList.Builder<ColumnStatistics> actualAdjusted = ImmutableList.builder();
        ImmutableMap.Builder<Integer, ColumnStatistics> actualAdjustedByNode = ImmutableMap.builder();
        for (int i = 1; i < actual.size(); i++) {
            if (!flattenedKeyToMapNodes.containsKey(i)) {
                actualAdjusted.add(actual.get(i));
                actualAdjustedByNode.put(i, actual.get(i));
            }
        }

        RowGroupStatistics expectedRowGroup = rowGroups.get(rowGroupIndex);
        RowGroupStatistics actualRowGroup = new RowGroupStatistics(BOTH, actualAdjustedByNode.build());

        if (expectedRowGroup.getValidationMode() != HASHED) {
            Map<Integer, ColumnStatistics> expectedByColumnIndex = expectedRowGroup.getColumnStatistics();

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Restore/re-download the file — it was likely modified or corrupted after writing
  2. Re-write the file with the Presto ORC writer
  3. Align row group size settings between writer and reader clusters if validation metadata is version-skewed
  4. Set orc.write-validation=false if reading files from other engines where this metadata is absent
Defensive patterns

Strategy: validation

Validate before calling

// Ensure row group size matches the writer's setting before enabling validation
// e.g. writer used 10000 rows per row group
assert session.getSystemProperty("orc_row_group_size").equals("1MB"); // keep aligned with writer

Try / catch

try {
    orcBatchReader.nextPage();
} catch (OrcCorruptionException e) {
    if (e.getMessage().contains("Unexpected row group")) {
        // file metadata altered; re-read with validation off or restore backup
    }
}

Prevention

When it happens

Trigger: validateRowGroupStatistics called with rowGroupIndex >= number of recorded row groups for the stripe at stripeOffset — typically a stripe whose ROW_INDEX entry count changed after write (file modified, corrupted footer/metadata).

Common situations: Files post-processed by compaction tools; partial/corrupted writes; reader and writer disagreeing on row-group sizing (different orc-row-group-size defaults).

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/d025f85b5ae99aef. Report an issue: GitHub.