{"record":{"id":"952b23f881b123f4","repo":"prestodb/presto","slug":"current-entry-must-be-closed-before-a-null-can-be-952b23","errorCode":null,"errorMessage":"Current entry must be closed before a null can be written","messagePattern":"Current entry must be closed before a null can be written","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"presto-common/src/main/java/com/facebook/presto/common/block/VariableWidthBlockBuilder.java","lineNumber":283,"sourceCode":"        }\n        sliceOutput.writeBytes(source, sourceIndex, length);\n        currentEntrySize += length;\n        return this;\n    }\n\n    @Override\n    public BlockBuilder closeEntry()\n    {\n        entryAdded(currentEntrySize, false);\n        currentEntrySize = 0;\n        return this;\n    }\n\n    @Override\n    public BlockBuilder appendNull()\n    {\n        if (currentEntrySize > 0) {\n            throw new IllegalStateException(\"Current entry must be closed before a null can be written\");\n        }\n\n        hasNullValue = true;\n        entryAdded(0, true);\n        return this;\n    }\n\n    private void entryAdded(int bytesWritten, boolean isNull)\n    {\n        if (!initialized) {\n            initializeCapacity();\n        }\n        if (valueIsNull.length <= positions) {\n            growCapacity();\n        }\n\n        valueIsNull[positions] = isNull;\n        offsets[positions + 1] = sliceOutput.size();","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-common/src/main/java/com/facebook/presto/common/block/VariableWidthBlockBuilder.java#L265-L301","documentation":"VariableWidthBlockBuilder.builds entries sequentially; an entry is 'open' while values have been written but the entry not yet closed (lengthEntry closed). appendNull cannot represent an open entry, so when currentEntrySize > 0 it throws IllegalStateException, requiring the caller to close the current entry first.","triggerScenarios":"Calling appendNull() after writing partial bytes into the current entry without closing it — i.e. beginEntry/writeBytes without matching closeEntry; seen in callers like readPositionFrom and various tests when a write path forgets to close an entry.","commonSituations":"Custom serialization code that writes bytes then decides the value is null; exception paths that abandon a half-written entry and continue appending; Parquet/ORC reader code paths writing partial values.","solutions":["Close the current entry (closeEntry()) before calling appendNull().","If the value must be null, do not write partial bytes; call appendNull instead of writing and abandoning the entry.","On error paths, reset the builder or finish/abandon the row before appending new values."],"exampleFix":"// before\nbuilder.writeBytes(slice, 0, 4);\nbuilder.appendNull(); // throws: entry still open\n// after\nbuilder.writeBytes(slice, 0, 4);\nbuilder.closeEntry();\nbuilder.appendNull();","handlingStrategy":"try-catch","validationCode":"if (isValueNull) {\n    // do not write partial bytes; go straight to appendNull\n    builder.appendNull();\n} else {\n    builder.writeBytes(...).closeEntry();\n}","typeGuard":null,"tryCatchPattern":"try {\n    builder.appendNull();\n} catch (IllegalStateException e) {\n    // entry still open: close or reset builder before continuing\n    builder.closeEntry();\n    builder.appendNull();\n}","preventionTips":["Decide null-ness before writing any entry bytes","Always pair writes with closeEntry(); use try/finally around entry writes","On error paths, reset or rebuild the builder instead of continuing to append"],"tags":["presto","block-builder","illegal-state","entry-lifecycle"],"backgroundTag":"unclosed-block-builder-entry","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"}