apache/druid · warning · ResponseException

error closing org.apache.druid.query.aggregation.Serializabl

Error message

error closing org.apache.druid.query.aggregation.SerializablePairLongStringComplexColumn

What it means

This error is thrown when the Closer held by a SerializablePairLongStringComplexColumn fails during close(). The column wraps resources (e.g. buffered selectors over serialized data) registered in a Guava Closer; if any underlying resource throws IOException while being released, the code wraps it in a RuntimeException (RE) with this message. It means cleanup failed, usually after the query/segment had already served its purpose.

Source

Thrown at processing/src/main/java/org/apache/druid/query/aggregation/SerializablePairLongStringComplexColumn.java:89

    // This can return nulls, meaning that it is expected that anything reading from this does
    // something "good" with null.  At time of writing, the relevan taggregators handle null properly
    return serde.deserialize(cellReader.getCell(rowNum));
  }

  @Override
  public int getLength()
  {
    return serializedSize;
  }

  @Override
  public void close()
  {
    try {
      closer.close();
    }
    catch (IOException e) {
      throw new RE(e, "error closing " + getClass().getName());
    }
  }

  public static class Builder
  {
    private final int serializedSize;
    private final SerializablePairLongStringDeltaEncodedStagedSerde serde;
    private final CellReader.Builder cellReaderBuilder;

    public Builder(ByteBuffer buffer)
    {
      ByteBuffer masterByteBuffer = buffer.asReadOnlyBuffer().order(ByteOrder.nativeOrder());

      serializedSize = masterByteBuffer.remaining();

      SerializablePairLongStringColumnHeader columnHeader =
          (SerializablePairLongStringColumnHeader) AbstractSerializablePairLongObjectColumnHeader.fromBuffer(masterByteBuffer, SerializablePairLongString.class);

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Inspect the chained IOException cause to find the real failing resource (file, selector, or stream) and fix the underlying I/O problem
  2. Check disk health, permissions, and free space on the segment cache directory
  3. Verify no query cancellation/interruption code closes column resources twice (double close can surface as IOException)
  4. Retry the query; if transient I/O errors persist, restart the Druid process to release leaked resources

Example fix

// before
try (ComplexColumn col = colFactory.makeComplexColumn("col")) {
  // use col, close failure becomes RuntimeException here
}
// after
try (ComplexColumn col = colFactory.makeComplexColumn("col")) {
  // use col
} catch (RuntimeException e) {
  if (e.getCause() instanceof IOException) {
    LOGGER.warn(e, "column close failed; underlying cause: %s", e.getCause());
  }
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Preconditions hard to validate; ensure resources opened successfully:
if (complexColumn != null && !complexColumn.isClosed()) { /* safe to use/close */ }

Type guard

boolean isUsable(ComplexColumn c) { return c != null && !c.isClosed(); }

Try / catch

try (ComplexColumn col = factory.makeComplexColumn(name)) {
  // use column
} catch (RuntimeException e) {
  if (e.getCause() instanceof IOException io) {
    throw new QueryInterruptedException(new ResourceLimitExceededException("column close failed: " + io));
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling close() on a SerializablePairLongStringComplexColumn (typically at query shutdown as the column factory is closed by the query lifecycle) while an underlying I/O resource throws an IOException.

Common situations: Disk I/O failures while closing memory-mapped or file-backed resources; interrupted/cancelled queries where resource cleanup races; full disks or flaky storage during query teardown.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/5cc1533876b7b5ea. Report an issue: GitHub.