{"record":{"id":"5cc1533876b7b5ea","repo":"apache/druid","slug":"error-closing-org-apache-druid-query-aggregation-s-5cc153","errorCode":null,"errorMessage":"error closing org.apache.druid.query.aggregation.SerializablePairLongStringComplexColumn","messagePattern":"error closing org\\.apache\\.druid\\.query\\.aggregation\\.SerializablePairLongStringComplexColumn","errorType":"exception","errorClass":"ResponseException","httpStatus":null,"severity":"warning","filePath":"processing/src/main/java/org/apache/druid/query/aggregation/SerializablePairLongStringComplexColumn.java","lineNumber":89,"sourceCode":"    // This can return nulls, meaning that it is expected that anything reading from this does\n    // something \"good\" with null.  At time of writing, the relevan taggregators handle null properly\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 SerializablePairLongStringDeltaEncodedStagedSerde 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      SerializablePairLongStringColumnHeader columnHeader =\n          (SerializablePairLongStringColumnHeader) AbstractSerializablePairLongObjectColumnHeader.fromBuffer(masterByteBuffer, SerializablePairLongString.class);\n","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/aggregation/SerializablePairLongStringComplexColumn.java#L71-L107","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the chained IOException cause to find the real failing resource (file, selector, or stream) and fix the underlying I/O problem","Check disk health, permissions, and free space on the segment cache directory","Verify no query cancellation/interruption code closes column resources twice (double close can surface as IOException)","Retry the query; if transient I/O errors persist, restart the Druid process to release leaked resources"],"exampleFix":"// before\ntry (ComplexColumn col = colFactory.makeComplexColumn(\"col\")) {\n  // use col, close failure becomes RuntimeException here\n}\n// after\ntry (ComplexColumn col = colFactory.makeComplexColumn(\"col\")) {\n  // use col\n} catch (RuntimeException e) {\n  if (e.getCause() instanceof IOException) {\n    LOGGER.warn(e, \"column close failed; underlying cause: %s\", e.getCause());\n  }\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":"// Preconditions hard to validate; ensure resources opened successfully:\nif (complexColumn != null && !complexColumn.isClosed()) { /* safe to use/close */ }","typeGuard":"boolean isUsable(ComplexColumn c) { return c != null && !c.isClosed(); }","tryCatchPattern":"try (ComplexColumn col = factory.makeComplexColumn(name)) {\n  // use column\n} catch (RuntimeException e) {\n  if (e.getCause() instanceof IOException io) {\n    throw new QueryInterruptedException(new ResourceLimitExceededException(\"column close failed: \" + io));\n  }\n  throw e;\n}","preventionTips":["Ensure the segment files and segment cache directory are writable and on healthy storage","Avoid closing column resources more than once; rely on try-with-resources","Monitor disk I/O errors and query cancellation logs around close time","Retry transient failures rather than crashing the query stack on close errors"],"tags":["io","resource-cleanup","java"],"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"}