prestodb/presto · error · IllegalStateException

Expected current entry to be closed but was opened

Error message

Expected current entry to be closed but was opened

What it means

appendStructure requires that no entry is currently open: it sets currentEntryOpened = true itself after validating. Calling it while a previous beginBlockEntry()/appendStructure entry is still open would nest entries and desynchronize field offsets, so the library throws IllegalStateException.

Source

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

            fieldBlocks[i] = fieldBlockBuilders[i].build();
        }
        return createRowBlockInternal(0, positionCount, hasNullRow ? rowIsNull : null, fieldBlockOffsets, fieldBlocks);
    }

    @Override
    public String toString()
    {
        return format("RowBlockBuilder(%d){numFields=%d, positionCount=%d", hashCode(), numFields, getPositionCount());
    }

    @Override
    public BlockBuilder appendStructure(Block block)
    {
        if (!(block instanceof AbstractSingleRowBlock)) {
            throw new IllegalStateException("Expected AbstractSingleRowBlock");
        }
        if (currentEntryOpened) {
            throw new IllegalStateException("Expected current entry to be closed but was opened");
        }
        currentEntryOpened = true;

        int blockPositionCount = block.getPositionCount();
        if (blockPositionCount != numFields) {
            throw new IllegalArgumentException(format("block position count (%s) is not equal to number of fields (%s)", blockPositionCount, numFields));
        }
        for (int i = 0; i < blockPositionCount; i++) {
            if (block.isNull(i)) {
                fieldBlockBuilders[i].appendNull();
            }
            else {
                block.writePositionTo(i, fieldBlockBuilders[i]);
            }
        }

        closeEntry();
        return this;

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Call closeEntry() after each appendStructure() before the next append
  2. Restructure copy loops: appendStructure(block); rowBuilder.closeEntry();
  3. Use try/finally around the copy loop body
  4. Never mix beginBlockEntry-based writes with appendStructure for the same row

Example fix

// before
for (int i = 0; i < block.getPositionCount(); i++) {
    rowBuilder.appendStructure(block.getBlock(i)); // second call throws: entry still open
}
// after
for (int i = 0; i < block.getPositionCount(); i++) {
    rowBuilder.appendStructure(block.getBlock(i));
    rowBuilder.closeEntry();
}
Defensive patterns

Strategy: validation

Validate before calling

// maintain open-entry state around appendStructure usage
boolean safeAppendStructure(RowBlockBuilder b, Block row) {
    // appendStructure must not be called while another entry is open;
    // ensure your wrapper never leaves an entry open:
    b.appendStructure(row);
    b.closeEntry(); // immediately close what appendStructure opened
    return true;
}

Try / catch

try {
    rowBuilder.appendStructure(block);
    rowBuilder.closeEntry();
} catch (IllegalStateException e) {
    if (e.getMessage().contains("Expected current entry to be closed")) {
        throw new IllegalStateException("nested appendStructure: previous entry not closed", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling appendStructure() after beginBlockEntry() without closeEntry(), or calling appendStructure() twice in a row without closing the entry opened by the first call.

Common situations: Bulk-copy loops copying row blocks that call appendStructure per position but forget that it auto-opens and requires closeEntry after each position; exception paths between appendStructure and closeEntry.

Related errors


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