prestodb/presto · error · IllegalStateException

Current entry must be closed before the block can be built

Error message

Current entry must be closed before the block can be built

What it means

build() refuses to materialize a Block while an entry write is still in progress (currentEntrySize > 0). The library requires every open entry to be closed (closeEntry) so the offsets array is consistent before a valid VariableWidthBlock can be constructed.

Source

Thrown at presto-common/src/main/java/com/facebook/presto/common/block/VariableWidthBlockBuilder.java:400

    {
        int positionCount = getPositionCount();
        checkValidRegion(positionCount, positionOffset, length);

        int[] newOffsets = compactOffsets(offsets, positionOffset, length);
        boolean[] newValueIsNull = null;
        if (hasNullValue) {
            newValueIsNull = compactArray(valueIsNull, positionOffset, length);
        }
        Slice slice = compactSlice(sliceOutput.getUnderlyingSlice(), offsets[positionOffset], newOffsets[length]);

        return new VariableWidthBlock(0, length, slice, newOffsets, newValueIsNull);
    }

    @Override
    public Block build()
    {
        if (currentEntrySize > 0) {
            throw new IllegalStateException("Current entry must be closed before the block can be built");
        }
        return new VariableWidthBlock(0, positions, sliceOutput.slice(), offsets, hasNullValue ? valueIsNull : null);
    }

    @Override
    public BlockBuilder newBlockBuilderLike(BlockBuilderStatus blockBuilderStatus)
    {
        int currentSizeInBytes = positions == 0 ? positions : (getOffset(positions) - getOffset(0));
        return new VariableWidthBlockBuilder(blockBuilderStatus, calculateBlockResetSize(positions), calculateBlockResetSize(currentSizeInBytes));
    }

    @Override
    public BlockBuilder newBlockBuilderLike(BlockBuilderStatus blockBuilderStatus, int expectedEntries)
    {
        int newSize = max(calculateBlockResetSize(positions), expectedEntries);
        int currentSizeInBytes = offsets[positions];
        return new VariableWidthBlockBuilder(blockBuilderStatus, newSize, BlockUtil.calculateNestedStructureResetSize(currentSizeInBytes, positions, newSize));
    }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Call closeEntry() after every writeBytes/writeSlice sequence, including the last one before build()
  2. Audit control flow so build() is only reached when no entry is open
  3. Wrap entry-writing loops in try/finally to close entries on failure paths, or discard the builder on error
  4. Replace an unfinished partial entry with writeNull() if the value should be null

Example fix

// before
builder.writeBytes(value, 0, value.length());
Block block = builder.build(); // throws
// after
builder.writeBytes(value, 0, value.length());
builder.closeEntry();
Block block = builder.build();
Defensive patterns

Strategy: validation

Validate before calling

// track open-entry state in your writer helper
boolean entryOpen = false;
// before build(): if (entryOpen) { builder.closeEntry(); entryOpen = false; }
Block block = builder.build();

Try / catch

try { return builder.build(); } catch (IllegalStateException e) { builder.closeEntry(); return builder.build(); }

Prevention

When it happens

Trigger: Calling build(), getSliceKeysBlock, or any of the block-producing helpers (sliceBlockAllNulls, sliceDictBlockSomeNulls) after writeBytes/writeSlice without a matching closeEntry(), or when the last entry's size is still buffered in currentEntrySize.

Common situations: Forgetting closeEntry() after the final write in a loop; an exception mid-write leaving an entry open; refactoring that moves build() earlier than entry completion; writing a null via writeNull instead of closeEntry ordering mistakes.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/5048a77a4861a3ec. Report an issue: GitHub.