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
- Pair every closeEntry() with exactly one preceding beginEntry()
- Add a boolean flag in caller code to track entry-open state
- 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
- Track entry-open state explicitly in caller code
- Always pair beginEntry/closeEntry, including on exception paths
- Prefer high-level writer helpers over manual lifecycle calls
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
- Invalid field position selection after nulls removed: " + se
- Current entry must be closed before a null can be written
- Current entry must be closed before the block can be built
- Expected current entry to be closed but was opened
- Response does not contain a JSON value
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/677bae918b4b1a80.
Report an issue: GitHub.