{"record":{"id":"db3684954a218fd1","repo":"apache/druid","slug":"error-closing-org-apache-druid-query-aggregation-s-db3684","errorCode":null,"errorMessage":"error closing org.apache.druid.query.aggregation.SerializablePairLongLongComplexColumn","messagePattern":"error closing org\\.apache\\.druid\\.query\\.aggregation\\.SerializablePairLongLongComplexColumn","errorType":"exception","errorClass":"ResponseException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/aggregation/SerializablePairLongLongComplexColumn.java","lineNumber":86,"sourceCode":"  public Object getRowValue(int rowNum)\n  {\n    return serde.deserialize(cellReader.getCell(rowNum));\n  }\n\n  @Override\n  public int getLength()\n  {\n    return serializedSize;\n  }\n\n  @Override\n  public void close()\n  {\n    try {\n      closer.close();\n    }\n    catch (IOException e) {\n      throw new RE(e, \"error closing \" + getClass().getName());\n    }\n  }\n\n  public static class Builder\n  {\n    private final int serializedSize;\n    private final AbstractSerializablePairLongObjectDeltaEncodedStagedSerde<?> serde;\n    private final CellReader.Builder cellReaderBuilder;\n\n    public Builder(ByteBuffer buffer)\n    {\n      ByteBuffer masterByteBuffer = buffer.asReadOnlyBuffer().order(ByteOrder.nativeOrder());\n\n      serializedSize = masterByteBuffer.remaining();\n\n      AbstractSerializablePairLongObjectColumnHeader<?> columnHeader =\n          AbstractSerializablePairLongObjectColumnHeader.fromBuffer(masterByteBuffer, SerializablePairLongLong.class);\n","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/aggregation/SerializablePairLongLongComplexColumn.java#L68-L104","documentation":"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.","triggerScenarios":"close() called when the underlying Closeable (channel/mapped file backing the serialized column) throws IOException on close.","commonSituations":"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.","solutions":["Inspect the wrapped IOException cause and address the underlying close failure (file, channel, or filesystem state)","Ensure single-owner closing — don't close the underlying resource both manually and via the Closer","Verify segment file lifecycle ordering so the column closes before its backing files are cleaned up","Check disk/filesystem health and permissions on the segment directory"],"exampleFix":"// before\ncloser.close(); // IOException propagates as RE\n// after\ntry {\n  closer.close();\n} catch (IOException e) {\n  LOG.warn(e, \"error closing %s\", getClass().getName());\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  column.close();\n} catch (RE e) {\n  if (e.getCause() instanceof IOException) {\n    LOG.warn(e, \"failed to close SerializablePairLongLongComplexColumn\");\n  } else {\n    throw e;\n  }\n}","preventionTips":["Ensure single-owner resource lifecycle; don't double-close registered Closeables","Close the column before segment files are removed from disk","Inspect RE causes to distinguish harmless already-closed cases from real I/O problems","Gracefully shut down tasks/queries so cleanup paths complete normally"],"tags":["java","io","resource-cleanup"],"backgroundTag":"file-close-failed","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"}