{"record":{"id":"8eb57cc4eb8d8737","repo":"apache/druid","slug":"unable-to-close-continuation","errorCode":null,"errorMessage":"Unable to close continuation","messagePattern":"Unable to close continuation","errorType":"exception","errorClass":"RE","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/operator/AbstractPartitioningOperator.java","lineNumber":166,"sourceCode":"        if (iter.hasNext()) {\n          return HandleContinuationResult.of(cont);\n        }\n\n        if (cont.subContinuation == null) {\n          // We were finished anyway\n          receiver.completed();\n          return HandleContinuationResult.of(null);\n        }\n\n        return HandleContinuationResult.of(new Continuation(null, cont.subContinuation));\n\n      case STOP:\n        receiver.completed();\n        try {\n          cont.close();\n        }\n        catch (IOException e) {\n          throw new RE(e, \"Unable to close continuation\");\n        }\n        return HandleContinuationResult.of(null);\n\n      default:\n        throw new RE(\"Unknown signal[%s]\", signal);\n    }\n  }\n\n  protected static class Continuation implements Closeable\n  {\n    Iterator<RowsAndColumns> iter;\n    Closeable subContinuation;\n\n    public Continuation(Iterator<RowsAndColumns> iter, Closeable subContinuation)\n    {\n      this.iter = iter;\n      this.subContinuation = subContinuation;\n    }","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/operator/AbstractPartitioningOperator.java#L148-L184","documentation":"AbstractPartitioningOperator.handleNonGoCases closes the Continuation (cont.close()) after receiving a STOP signal. If closing the continuation throws IOException, it is rethrown as this RE, since a resource underlying the continuation could not be released.","triggerScenarios":"A downstream operator signals STOP (e.g. limit reached, query cancelled) and cont.close() — which may close an underlying file/channel resource — throws IOException during cleanup.","commonSituations":"Cancelling or early-terminating window operator queries over disk-backed segments where closing the backing resource hits an I/O error (device error, file already closed by another path).","solutions":["Inspect the cause (RE wraps the IOException) to find the underlying I/O failure and address it (disk, file handle exhaustion)","Retry the query; transient close failures usually indicate underlying storage trouble","Report to maintainers if it reproduces consistently — the continuation implementation may be double-closing"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  operator.go(receiver, cont);\n} catch (ResourceLimitExceededException | RE e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"Unable to close continuation\")) {\n    logger.warn(e.getCause(), \"Continuation close failed; underlying resource may need cleanup\");\n  } else throw e;\n}","preventionTips":["Keep underlying segment storage healthy (disk checks, fd limits) so close() doesn't fail","Avoid duplicated close paths for continuation-backed resources","Investigate root-cause IOException from the wrapped cause rather than retrying blindly"],"tags":["io","operator","resource-cleanup","stop-signal"],"backgroundTag":"broken-pipe","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}