apache/druid · error · IllegalStateException
written out already
Error message
written out already
What it means
CompressedBlockSerializer.addValue(byte[]) throws IllegalStateException("written out already") when uncompressedDataBuffer is null, i.e., the serializer has already been finished (close()/writeEndBuffer ran) and its buffers were released. No further values can be accepted after write-out.
Source
Thrown at processing/src/main/java/org/apache/druid/segment/data/CompressedBlockSerializer.java:85
)
{
this.segmentWriteOutMedium = segmentWriteOutMedium;
this.compression = compression;
this.compressor = compression.getCompressor();
this.uncompressedDataBuffer = compressor.allocateInBuffer(blockSize, closer).order(ByteOrder.nativeOrder());
this.compressedDataBuffer = compressor.allocateOutBuffer(blockSize, closer).order(ByteOrder.nativeOrder());
}
public void open() throws IOException
{
headerOut = segmentWriteOutMedium.makeWriteOutBytes();
valuesOut = segmentWriteOutMedium.makeWriteOutBytes();
}
public void addValue(byte[] bytes) throws IOException
{
if (uncompressedDataBuffer == null) {
throw new IllegalStateException("written out already");
}
flushIfNeeded();
if (bytes.length <= uncompressedDataBuffer.remaining()) {
uncompressedDataBuffer.put(bytes);
} else {
int written = 0;
// write until we have had our fill, flushing buffers as needed
while (written < bytes.length) {
int next = Math.min(uncompressedDataBuffer.remaining(), bytes.length - written);
uncompressedDataBuffer.put(bytes, written, next);
written += next;
flushIfNeeded();
}
}
}
public void addValue(ByteBuffer bytes) throws IOExceptionView on GitHub (pinned to 9b90983fd2)
Solutions
- Complete all addValue calls before calling close/writeEndBuffer
- Fix ordering in custom encoders so value writing precedes finalization
- Do not reuse serializer instances after close; create a new one per column
- Add an assertion/flag in wrapping code to catch late adds
Example fix
// before
serializer.addValue(bytes); // after close()
// after
if (serializer.isOpen()) {
serializer.addValue(bytes);
} Defensive patterns
Strategy: validation
Validate before calling
if (uncompressedDataBuffer == null || closed) {
throw new IllegalStateException("CompressedBlockSerializer already written out");
} Try / catch
try {
serializer.addValue(bytes);
} catch (IllegalStateException e) {
if (e.getMessage().contains("written out already")) {
// reopen a new serializer for remaining values
serializer = createSerializer();
serializer.addValue(bytes);
} else throw e;
} Prevention
- Call close() only after all values are added
- Track open/closed state in wrapping code
- Avoid double-close paths in plugins
- Unit-test encoder lifecycle ordering
When it happens
Trigger: Calling addValue(byte[]) after close() or after the end buffer was written during segment serialization.
Common situations: Custom dictionary/value encoders that keep adding values after the column is finalized; plugin code with wrong lifecycle ordering between value collection and column close; reusing a closed serializer for another batch.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/19188f1f55501998.
Report an issue: GitHub.