prestodb/presto · error · PrestoException
ICEBERG_BAD_DATA
ICEBERG_BAD_DATA
Error message
Expecting Page with one channel but got N
What it means
IcebergDeletePageSink's inner appendPage expects a single-channel page containing just the row-position block (it wraps it with the data-file path as an RLE block to build the delete-file row). Any other channel count triggers this ICEBERG_BAD_DATA exception because the page shape is invalid for position deletes.
Source
Thrown at presto-iceberg/src/main/java/com/facebook/presto/iceberg/delete/IcebergDeletePageSink.java:197
{
this.writer = createWriter();
}
/**
* @param page Only one channel. It contains the list of row positions to delete.
*/
public void appendPage(Page page)
{
if (page.getChannelCount() == 1) {
hdfsEnvironment.doAs(session.getUser(), () -> {
Block[] blocks = new Block[2];
blocks[0] = new RunLengthEncodedBlock(nativeValueToBlock(VarcharType.VARCHAR, utf8Slice(dataFile)), page.getPositionCount());
blocks[1] = page.getBlock(0);
writer.appendRows(new Page(blocks));
});
}
else {
throw new PrestoException(ICEBERG_BAD_DATA, "Expecting Page with one channel but got " + page.getChannelCount());
}
}
public IcebergFileWriter getWriter()
{
return writer;
}
public long getSystemMemoryUsage()
{
return writer.getSystemMemoryUsage();
}
private IcebergFileWriter createWriter()
{
return fileWriterFactory.createFileWriter(
outputPath,
positionDeleteSchema,View on GitHub (pinned to 55bb57d202)
Solutions
- Pass a page with exactly one channel holding the delete positions (BIGINT); the sink adds the file path itself.
- If your page already has path+position, drop the path channel before appending.
- Check upstream operators for an accidental extra projection column feeding the delete sink.
Example fix
// before sink.appendPage(new Page(positionBlock, pathBlock)); // after sink.appendPage(new Page(positionBlock)); // only the position channel
Defensive patterns
Strategy: validation
Validate before calling
if (page.getChannelCount() != 1) {
throw new IllegalArgumentException("Delete sink expects a single position channel, got " + page.getChannelCount());
} Type guard
boolean isSingleChannelPositionPage(Page page) {
return page.getChannelCount() == 1 && page.getBlock(0) instanceof BigintBlock;
} Try / catch
try { sink.appendPage(page); } catch (PrestoException e) { if (e.getErrorCode() == ICEBERG_BAD_DATA.toErrorCode()) { /* rebuild page with one channel */ } throw e; } Prevention
- Feed only the position column to the delete sink
- Do not pre-add the data-file path column
- Add channel-count assertions in delete-writing pipelines
When it happens
Trigger: Calling appendPage on the delete sink with a Page whose channel count is not 1 (e.g. page already contains path+position columns, or an empty/misconstructed page).
Common situations: Custom delete-writing code passing pages with (path,pos) pairs already merged; a plan bug upstream producing extra columns; misuse of the internal sink API.
Related errors
- ICEBERG_BAD_DATA
- ICEBERG_BAD_DATA
- ICEBERG_ROLLBACK_ERROR
- Invalid position %s and length %s in page with %s positions
- Block does not have same position count
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/2116d0acc175ea78.
Report an issue: GitHub.