{"record":{"id":"9f5ed028fbf2aad4","repo":"apache/druid","slug":"failed-to-call-cleaner-of-class-s","errorCode":null,"errorMessage":"Failed to call cleaner of class[%s]","messagePattern":"Failed to call cleaner of class\\[(.+?)\\]","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"processing/src/main/java/org/apache/druid/common/asyncresource/SettableAsyncResource.java","lineNumber":274,"sourceCode":"    final Closeable deferredCloseable;\n\n    synchronized (this) {\n      deferredCloseable = switch (state) {\n        case NEW -> canceler != null ? canceler::run : null;\n        case READY -> result;\n        case RELEASED -> null;\n        default -> throw DruidException.defensive(\"Already closed\");\n      };\n\n      // Clear result and canceler to allow GC.\n      result = null;\n      canceler = null;\n      state = State.CLOSED;\n    }\n\n    CloseableUtils.closeAndSuppressExceptions(\n        deferredCloseable,\n        e -> LOG.warn(e, \"Failed to call cleaner of class[%s]\", deferredCloseable.getClass())\n    );\n  }\n\n  @GuardedBy(\"this\")\n  private List<Runnable> drainCallbacks()\n  {\n    final List<Runnable> snapshot = List.copyOf(readyCallbacks);\n    readyCallbacks.clear();\n    return snapshot;\n  }\n\n  private boolean setInternal(Either<Throwable, ResourceHolder<T>> value)\n  {\n    final boolean didSet;\n    final List<Runnable> callbacksToFire;\n\n    synchronized (this) {\n      didSet = switch (state) {","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/common/asyncresource/SettableAsyncResource.java#L256-L292","documentation":"SettableAsyncResource.close() invokes a deferred cleaner (a Closeable created at construction) via CloseableUtils.closeAndSuppressExceptions, and logs a warning if that cleaner's close() throws. The resource is still marked CLOSED; the exception is suppressed because close failures of the cleaner are non-fatal, typically meaning some underlying buffer/file was already released or the cleaner failed to run.","triggerScenarios":"Calling SettableAsyncResource.close() when the deferred cleaner's close() throws, e.g. the cleaner tries to free a native buffer, file handle, or off-heap resource and hits an IOException or IllegalStateException because the resource was already released elsewhere.","commonSituations":"Double-close of a resource (both a query-cancellation path and normal close call close()); cleaner referencing off-heap memory already freed by the JVM/other shutdown hook; shutdown sequence where the underlying allocator is closed before the async resource.","solutions":["Inspect the nested warning for the cleaner's class name and root exception (usually AlreadyClosedException or IOException)","Avoid closing the same SettableAsyncResource from multiple code paths; centralize ownership of close()","Ensure shutdown ordering closes dependent allocators/byte-buffers after all SettableAsyncResource instances","If the warning is noisy but harmless (double-close pattern), guard close() with the resource's state check before calling"],"exampleFix":"// before\nresource.close(); // called in two paths, second close trips cleaner\n// after\nif (!resource.isClosed()) {\n  resource.close();\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Suppress-and-log pattern mirrors the library\ntry {\n  resource.close();\n} catch (Exception e) {\n  log.warn(e, \"Ignoring close failure of async resource\");\n}","preventionTips":["Close each SettableAsyncResource exactly once from a single owner","Use try-with-resources or a finally block so close ordering is deterministic","Close dependent allocators after async resources, never before","Monitor warnings for repeated AlreadyClosedException, which signals double-close bugs"],"tags":["resource-cleanup","close","suppressed-exception"],"backgroundTag":"resource-cleanup-failed","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"}