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 IOException

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Complete all addValue calls before calling close/writeEndBuffer
  2. Fix ordering in custom encoders so value writing precedes finalization
  3. Do not reuse serializer instances after close; create a new one per column
  4. 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

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.