prestodb/presto · error · PrestoException
CORRUPT_PAGE
CORRUPT_PAGE
Error message
delegate page channels do not match expected number of channels
What it means
The ChangelogPageSource's ROWDATA column converter expects the delegate page's channel count to exactly equal the number of fields in the changelog's inner row type, since channels are wrapped into a RowBlock. A mismatch means the underlying page doesn't correspond to the declared row schema, so CORRUPT_PAGE is thrown to avoid producing a malformed row block.
Source
Thrown at presto-iceberg/src/main/java/com/facebook/presto/iceberg/changelog/ChangelogPageSource.java:130
return delegate.getSystemMemoryUsage();
}
@Override
public void close()
throws IOException
{
delegate.close();
}
public enum ChangelogSchemaColumns
{
OPERATION((source, page) -> RunLengthEncodedBlock.create(VARCHAR, Slices.utf8Slice(source.changelogSplitInfo.getOperation().toString()), page.getPositionCount())),
ORDINAL((source, page) -> RunLengthEncodedBlock.create(BIGINT, source.changelogSplitInfo.getOrdinal(), page.getPositionCount())),
SNAPSHOTID((source, page) -> RunLengthEncodedBlock.create(BIGINT, source.changelogSplitInfo.getSnapshotId(), page.getPositionCount())),
ROWDATA((source, page) -> {
if (source.innerRowType.getFields().size() != page.getChannelCount()) {
throw new PrestoException(CORRUPT_PAGE, "delegate page channels do not match expected number of channels");
}
Block[] channels = new Block[page.getChannelCount()];
for (int i = 0; i < page.getChannelCount(); i++) {
channels[i] = page.getBlock(i);
}
return RowBlock.fromFieldBlocks(page.getPositionCount(), Optional.empty(), channels);
});
private final ChangelogUtil.Function2<ChangelogPageSource, Page, Block> blockSupplier;
ChangelogSchemaColumns(ChangelogUtil.Function2<ChangelogPageSource, Page, Block> blockSupplier)
{
this.blockSupplier = blockSupplier;
}
public Block getBlock(ChangelogPageSource pageSource, Page page)
{
return blockSupplier.apply(pageSource, page);View on GitHub (pinned to 55bb57d202)
Solutions
- Re-run the query so splits are re-planned against the current table schema.
- Verify the changelog split's innerRowType matches the actual file schema; fix metadata caching if it doesn't.
- Check for schema-evolution operations (ADD/DROP COLUMN) concurrent with the changelog query.
Example fix
// before: channels from stale schema
RowBlock.fromFieldBlocks(page.getPositionCount(), Optional.empty(), channels);
// after: guard before building
if (source.innerRowType.getFields().size() != page.getChannelCount()) {
throw new PrestoException(CORRUPT_PAGE, "delegate page channels do not match expected number of channels");
} Defensive patterns
Strategy: retry
Type guard
boolean pageMatchesRowType(Page page, RowType innerRowType) {
return page.getChannelCount() == innerRowType.getFields().size();
} Try / catch
try { return pageSource.getNextPage(); } catch (PrestoException e) { if (e.getErrorCode() == CORRUPT_PAGE.toErrorCode()) { /* re-plan split against current schema */ } throw e; } Prevention
- Avoid concurrent schema evolution during changelog queries
- Re-plan queries after ADD/DROP COLUMN
- Verify split metadata freshness against current table schema
When it happens
Trigger: getNextPage on a changelog split where source.innerRowType.getFields().size() differs from page.getChannelCount() — e.g. stale split metadata after schema evolution, or a delegate source emitting extra/missing columns.
Common situations: Iceberg table schema changed (columns added/dropped) between split planning and execution; reading a changelog with an outdated cached schema.
Related errors
- ICEBERG_MISSING_COLUMN
- ICEBERG_MISSING_COLUMN
- NOT_SUPPORTED
- ICEBERG_CANNOT_OPEN_SPLIT
- currentFieldIndexToWrite is not valid
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/eb5eed8c680f5b66.
Report an issue: GitHub.