prestodb/presto · error · IllegalStateException

Expected entry to be opened but was closed

Error message

Expected entry to be opened but was closed

What it means

RowBlockBuilder.closeEntry finalizes the current row entry and requires that an entry was opened (via beginEntry / entry lifecycle) beforehand. Calling closeEntry without a matching open is a lifecycle misuse, so it throws IllegalStateException. The builder tracks this with currentEntryOpened.

Source

Thrown at presto-common/src/main/java/com/facebook/presto/common/block/RowBlockBuilder.java:183

    {
        if (currentEntryOpened) {
            throw new IllegalStateException("Expected current entry to be closed but was opened");
        }
        currentEntryOpened = true;
    }

    @Override
    public SingleRowBlockWriter beginBlockEntry()
    {
        beginDirectEntry();
        return new SingleRowBlockWriter(fieldBlockBuilders[0].getPositionCount(), fieldBlockBuilders);
    }

    @Override
    public BlockBuilder closeEntry()
    {
        if (!currentEntryOpened) {
            throw new IllegalStateException("Expected entry to be opened but was closed");
        }

        entryAdded(false);
        currentEntryOpened = false;
        return this;
    }

    @Override
    public BlockBuilder appendNull()
    {
        if (currentEntryOpened) {
            throw new IllegalStateException("Current entry must be closed before a null can be written");
        }

        entryAdded(true);
        return this;
    }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Pair every closeEntry() with exactly one preceding beginEntry()
  2. Add a boolean flag in caller code to track entry-open state
  3. Use higher-level helpers (buildFieldChildren / element writers) that manage the lifecycle

Example fix

// before
rowBlockBuilder.closeEntry(); // may be called twice on some paths
// after
if (rowBlockBuilder != null && entryOpen) {
    rowBlockBuilder.closeEntry();
    entryOpen = false;
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!entryOpen) {
    throw new IllegalStateException("closeEntry called without beginEntry");
}
rowBlockBuilder.closeEntry();

Try / catch

try {
    rowBlockBuilder.closeEntry();
} catch (IllegalStateException e) {
    // correct builder lifecycle management in caller
}

Prevention

When it happens

Trigger: Calling closeEntry() on a RowBlockBuilder with currentEntryOpened == false — e.g. double closeEntry, closeEntry before writing any field, or reusing a builder after a previous entry was closed without opening a new one.

Common situations: Custom serializers or aggregation code that manually drives the builder API and mishandles the begin/close pairing, especially across conditional branches or exception paths.

Related errors


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