{"record":{"id":"b9eceb2c2be26261","repo":"prestodb/presto","slug":"singlerowblock-does-not-support-appendnull","errorCode":null,"errorMessage":"SingleRowBlock does not support appendNull()","messagePattern":"SingleRowBlock does not support appendNull\\(\\)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"presto-common/src/main/java/com/facebook/presto/common/block/SingleRowBlock.java","lineNumber":122,"sourceCode":"    {\n        return format(\"SingleRowBlock(%d){numFields=%d}\", hashCode(), fieldBlocks.length);\n    }\n\n    @Override\n    public Block getLoadedBlock()\n    {\n        Block[] loadedFieldBlocks = ensureBlocksAreLoaded(fieldBlocks);\n        if (loadedFieldBlocks == fieldBlocks) {\n            // All blocks are already loaded\n            return this;\n        }\n        return new SingleRowBlock(rowIndex, loadedFieldBlocks);\n    }\n\n    @Override\n    public Block appendNull()\n    {\n        throw new UnsupportedOperationException(\"SingleRowBlock does not support appendNull()\");\n    }\n\n    @Override\n    public boolean equals(Object obj)\n    {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null || getClass() != obj.getClass()) {\n            return false;\n        }\n        SingleRowBlock other = (SingleRowBlock) obj;\n        return Arrays.equals(this.fieldBlocks, other.fieldBlocks);\n    }\n\n    @Override\n    public int hashCode()\n    {","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-common/src/main/java/com/facebook/presto/common/block/SingleRowBlock.java#L104-L140","documentation":"SingleRowBlock is an immutable view over one row of an existing RowBlock. It does not support mutation, so appendNull() throws UnsupportedOperationException. Nulls belong in a RowBlockBuilder, not in a view over already-written data.","triggerScenarios":"Calling appendNull() on a SingleRowBlock, usually in generic code that appends to any Block without checking its type (e.g. building output pages row by row).","commonSituations":"Generic block-processing operators hitting a row-typed column; code assuming all blocks are mutable; using SingleRowBlock where a RowBlockBuilder was needed to assemble new rows.","solutions":["Use a RowBlockBuilder and call appendNull() (or build field-wise) there instead.","Copy the SingleRowBlock's fields into a builder via writePositionTo per field when mutation-free copying is the goal.","Type-check with instanceof SingleRowBlock / RowBlock and route immutable blocks through a builder-based copy path."],"exampleFix":"// before\nBlock row = rowColumn.getBlock(position);\nBlock out = row.appendNull(); // UnsupportedOperationException\n// after\nRowBlockBuilder out = (RowBlockBuilder) rowType.createBlockBuilder(null, 1);\nout.appendNull(); // writes a NULL row into the builder","handlingStrategy":"type-guard","validationCode":"if (block instanceof SingleRowBlock) {\n    // read-only view: copy fields into a RowBlockBuilder before any mutation\n}","typeGuard":"boolean isAppendableBlock(Block block) {\n    return block instanceof BlockBuilder;\n}","tryCatchPattern":"try {\n    newBlock = block.appendNull();\n} catch (UnsupportedOperationException e) {\n    RowBlockBuilder builder = (RowBlockBuilder) rowType.createBlockBuilder(null, 1);\n    builder.appendNull();\n    newBlock = builder.build();\n}","preventionTips":["Treat SingleRowBlock (from getBlock/getSingleValueBlock) as strictly read-only.","Assemble new rows only via RowBlockBuilder.","Centralize block-copy logic so mutation attempts on views fail at review time, not runtime."],"tags":["presto","block","unsupported-operation","immutable","rowblock"],"backgroundTag":"unsupported-block-mutation","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"}