apache/druid · error · ResponseException

error closing…

Error message

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

What it means

SerializablePairLongLongComplexColumn.close() releases resources through a Closer; if closing the wrapped Closeable throws IOException it is rethrown as a Druid RE with 'error closing <class name>'. This indicates cleanup of the serialized pair-long-long column failed, risking leaked file handles or mapped memory.

Solutions

  1. Inspect the wrapped IOException cause and address the underlying close failure (file, channel, or filesystem state)
  2. Ensure single-owner closing — don't close the underlying resource both manually and via the Closer
  3. Verify segment file lifecycle ordering so the column closes before its backing files are cleaned up
  4. Check disk/filesystem health and permissions on the segment directory

Example fix

// before
closer.close(); // IOException propagates as RE
// after
try {
  closer.close();
} catch (IOException e) {
  LOG.warn(e, "error closing %s", getClass().getName());
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  column.close();
} catch (RE e) {
  if (e.getCause() instanceof IOException) {
    LOG.warn(e, "failed to close SerializablePairLongLongComplexColumn");
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: close() called when the underlying Closeable (channel/mapped file backing the serialized column) throws IOException on close.

Common situations: Underlying segment file already closed/deleted during query cleanup races; NFS/disk errors; double-close of the same channel; abrupt task termination leaving descriptors in a bad state.

Related errors


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

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/query/aggregation/SerializablePairLongLongComplexColumn.java:86

  public Object getRowValue(int rowNum)
  {
    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 AbstractSerializablePairLongObjectDeltaEncodedStagedSerde<?> serde;
    private final CellReader.Builder cellReaderBuilder;

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

      serializedSize = masterByteBuffer.remaining();

      AbstractSerializablePairLongObjectColumnHeader<?> columnHeader =
          AbstractSerializablePairLongObjectColumnHeader.fromBuffer(masterByteBuffer, SerializablePairLongLong.class);

View on GitHub (pinned to 9b90983fd2)