{"record":{"id":"17b434d5f8bbfad1","repo":"prestodb/presto","slug":"invalid-channel-d-in-page-with-s-channels","errorCode":null,"errorMessage":"Invalid channel %d in page with %s channels","messagePattern":"Invalid channel (.+?) in page with (.+?) channels","errorType":"exception","errorClass":"java.lang.IndexOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"presto-common/src/main/java/com/facebook/presto/common/Page.java","lineNumber":435,"sourceCode":"    }\n\n    public Page prependColumn(Block column)\n    {\n        if (column.getPositionCount() != positionCount) {\n            throw new IllegalArgumentException(String.format(\"Column does not have same position count (%s) as page (%s)\", column.getPositionCount(), positionCount));\n        }\n\n        Block[] result = new Block[blocks.length + 1];\n        result[0] = column;\n        System.arraycopy(blocks, 0, result, 1, blocks.length);\n\n        return wrapBlocksWithoutCopy(positionCount, result);\n    }\n\n    public Page dropColumn(int channelIndex)\n    {\n        if (channelIndex < 0 || channelIndex >= getChannelCount()) {\n            throw new IndexOutOfBoundsException(format(\"Invalid channel %d in page with %s channels\", channelIndex, getChannelCount()));\n        }\n\n        Block[] result = new Block[getChannelCount() - 1];\n        System.arraycopy(blocks, 0, result, 0, channelIndex);\n        System.arraycopy(blocks, channelIndex + 1, result, channelIndex, getChannelCount() - channelIndex - 1);\n        return wrapBlocksWithoutCopy(positionCount, result);\n    }\n\n    private long updateRetainedSize()\n    {\n        AtomicLong retainedSizeInBytes = new AtomicLong(INSTANCE_SIZE + sizeOf(blocks));\n        Set<Object> referenceSet = newSetFromMap(new IdentityHashMap<>());\n        for (Block block : blocks) {\n            block.retainedBytesForEachPart((object, size) -> {\n                if (referenceSet.add(object)) {\n                    retainedSizeInBytes.addAndGet(size);\n                }\n            });","sourceCodeStart":417,"sourceCodeEnd":453,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-common/src/main/java/com/facebook/presto/common/Page.java#L417-L453","documentation":"Page.dropColumn removes the channel at channelIndex; the index must be within [0, channelCount). Out-of-range values would otherwise corrupt the block array copy, so the library throws IndexOutOfBoundsException.","triggerScenarios":"Calling page.dropColumn(i) with i < 0 or i >= page.getChannelCount() — e.g. dropping the same column twice, or using a channel index from a stale/different page layout.","commonSituations":"fillInRowIDs-style pipelines that drop a channel twice; operators hardcoding channel indexes after the page schema changed; dynamic column removal loops without bounds checks.","solutions":["Check 0 <= channelIndex < page.getChannelCount() before calling dropColumn","Track which columns have already been dropped to avoid double-drop","Derive channel indexes from the actual page schema (e.g. by locating the column by type/name) instead of hardcoding"],"exampleFix":"// before\npage.dropColumn(rowIdChannel);\npage.dropColumn(rowIdChannel); // second call throws\n// after\nif (rowIdChannel >= 0 && rowIdChannel < page.getChannelCount()) {\n    page = page.dropColumn(rowIdChannel);\n    rowIdChannel = -1;\n}","handlingStrategy":"type-guard","validationCode":"if (channelIndex < 0 || channelIndex >= page.getChannelCount()) {\n    throw new IllegalArgumentException(\"cannot drop channel \" + channelIndex\n        + \" from page with \" + page.getChannelCount() + \" channels\");\n}\npage = page.dropColumn(channelIndex);","typeGuard":"boolean canDrop(Page page, int channelIndex) {\n    return channelIndex >= 0 && channelIndex < page.getChannelCount();\n}","tryCatchPattern":"try {\n    page = page.dropColumn(channelIndex);\n} catch (IndexOutOfBoundsException e) {\n    if (!e.getMessage().contains(\"Invalid channel\")) throw e;\n    return page; // channel already absent\n}","preventionTips":["Recompute channel indexes after each schema change (dropColumn shifts later columns)","Guard against double-dropping the same channel","Resolve channel indexes by type/name rather than hardcoding"],"tags":["presto","page","index-out-of-bounds","channel-index"],"backgroundTag":"index-out-of-bounds","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}