apache/druid · error · IllegalStateException

written out already

Error message

written out already

What it means

BlockLayoutColumnarLongsSerializer.add(long) throws IllegalStateException("written out already") when the serializer was already closed: endBuffer is null after the column data has been written out. Adds after close violate the serializer's lifecycle and would corrupt the segment, so the call fails fast.

Source

Thrown at processing/src/main/java/org/apache/druid/segment/data/BlockLayoutColumnarLongsSerializer.java:102

  }

  @Override
  public void open() throws IOException
  {
    flattener.open();
  }

  @Override
  public int size()
  {
    return numInserted;
  }

  @Override
  public void add(long value) throws IOException
  {
    if (endBuffer == null) {
      throw new IllegalStateException("written out already");
    }
    if (numInserted == numInsertedForNextFlush) {
      numInsertedForNextFlush += sizePer;
      writer.flush();
      endBuffer.flip();
      flattener.write(endBuffer);
      endBuffer.clear();
      writer.setBuffer(endBuffer);
    }

    writer.write(value);
    ++numInserted;
    if (numInserted < 0) {
      throw new ColumnCapacityExceededException(columnName);
    }
  }

  @Override

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Ensure all add(long) calls complete before closing the serializer/segment
  2. Audit custom code for lifecycle violations (add-after-close)
  3. Avoid reusing serializer instances across multiple segments
  4. Add a defensive 'open' flag in wrapper code to detect late adds

Example fix

// before
longSerializer.add(value); // after close
// after
assert !isClosed : "serializer already written out";
longSerializer.add(value);
Defensive patterns

Strategy: validation

Validate before calling

if (closed) {
  throw new IllegalStateException("Cannot add long values after serializer close");
}

Try / catch

try {
  serializer.add(value);
} catch (IllegalStateException e) {
  if ("written out already".equals(e.getMessage())) {
    throw new IllegalStateException("Lifecycle bug: add(long) after close", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling add(long) after close() or after the underlying WriteOutBytes was flushed and buffers nulled during segment serialization.

Common situations: Custom extension code writing rows after segment close; reusing a finished column serializer; race conditions in concurrent ingestion plugins.

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/0afcc48484f5d0f4. Report an issue: GitHub.