{"record":{"id":"8072f5f04217464d","repo":"apache/druid","slug":"written-out-already-8072f5","errorCode":null,"errorMessage":"written out already","messagePattern":"written out already","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/data/BlockLayoutColumnarFloatsSerializer.java","lineNumber":94,"sourceCode":"  }\n\n  @Override\n  public void open() throws IOException\n  {\n    flattener.open();\n  }\n\n  @Override\n  public int size()\n  {\n    return numInserted;\n  }\n\n  @Override\n  public void add(float value) throws IOException\n  {\n    if (endBuffer == null) {\n      throw new IllegalStateException(\"written out already\");\n    }\n    if (!endBuffer.hasRemaining()) {\n      endBuffer.rewind();\n      flattener.write(endBuffer);\n      endBuffer.clear();\n    }\n    endBuffer.putFloat(value);\n    ++numInserted;\n    if (numInserted < 0) {\n      throw new ColumnCapacityExceededException(columnName);\n    }\n  }\n\n  @Override\n  public long getSerializedSize() throws IOException\n  {\n    writeEndBuffer();\n    return META_SERDE_HELPER.size(this) + flattener.getSerializedSize();","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/data/BlockLayoutColumnarFloatsSerializer.java#L76-L112","documentation":"BlockLayoutColumnarFloatsSerializer.add(float) throws IllegalStateException(\"written out already\") when the serializer has already been closed out (endBuffer set to null after the column was written). After close/serialization the serializer no longer accepts values. This is a lifecycle-state violation, not an I/O error.","triggerScenarios":"Calling add(float) after close() or after the serializer's buffers were written out via a WriteOutBytes flush — endBuffer is null at that point.","commonSituations":"Custom ingestion/indexing code that keeps a serializer reference alive after finalizing the column; bugs in custom plugins (e.g., custom aggregations or extensions) that write rows out of order or after segment close.","solutions":["Fix the writer so add() is never called after close()/write-out; finish all adds first","Check for double-close or reuse of a finished IncrementalIndex/segment writer","If using custom plugin code, capture all values before closing the column","Guard with an internal flag so callers cannot add after finalize"],"exampleFix":"// before\nserializer.add(value); // may run after close()\n// after\nif (!closed) {\n  serializer.add(value);\n}","handlingStrategy":"validation","validationCode":"// guard the lifecycle before adding\nif (serializer == null || isClosed(serializer)) {\n  throw new IllegalStateException(\"Attempt to add after serializer close\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  serializer.add(value);\n} catch (IllegalStateException e) {\n  if (e.getMessage().contains(\"written out already\")) {\n    // open a fresh serializer and replay the value\n    serializer = newSerializer();\n    serializer.add(value);\n  } else throw e;\n}","preventionTips":["Never call add() after close(); enforce ordering in wrapper code","Avoid sharing serializers across threads without synchronization","Create a new serializer per column/segment","Add an isClosed flag to your ingestion pipeline"],"tags":["druid","segment","illegal-state","lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}