{"record":{"id":"3878a018a0b0616a","repo":"apache/druid","slug":"expected-0-resource-count-got-d-object-was-s","errorCode":null,"errorMessage":"Expected 0 resource count, got [%d]! Object was[%s].","messagePattern":"Expected 0 resource count, got \\[(.+?)\\]! Object was\\[(.+?)\\]\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/src/main/java/org/apache/druid/client/cache/MemcacheClientPool.java","lineNumber":157,"sourceCode":"\n  private static class ClientLeakNotifier implements Runnable\n  {\n    private final AtomicInteger count;\n    private final MemcachedClientIF clientIF;\n\n    private ClientLeakNotifier(AtomicInteger count, MemcachedClientIF clientIF)\n    {\n      this.count = count;\n      this.clientIF = clientIF;\n    }\n\n    @Override\n    public void run()\n    {\n      final int shouldBeZero = count.get();\n      if (shouldBeZero != 0) {\n        LEAKED_CLIENTS.incrementAndGet();\n        log.warn(\"Expected 0 resource count, got [%d]! Object was[%s].\", shouldBeZero, clientIF);\n      }\n    }\n  }\n}\n","sourceCodeStart":139,"sourceCodeEnd":162,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/client/cache/MemcacheClientPool.java#L139-L162","documentation":"MemcacheClientPool tracks active memcached client leases with a reference count. A watchdog runnable runs at shutdown/pool cleanup and expects the count to be zero; if not, a client was never returned to the pool (leaked). It increments a LEAKED_CLIENTS counter and logs the offending client factory — a diagnostic for a resource leak, not a thrown exception.","triggerScenarios":"The pool's checker run() observes count.get() != 0, meaning some code path acquired a memcached client from the pool and did not release it (missing returnClient/close, exception bypassing release).","commonSituations":"Exception thrown between client acquisition and release without try/finally; broker shutdown while cache population in flight; long-running queries holding clients beyond the check interval; Druid version bugs in cache pool lifecycle.","solutions":["Ensure every client acquisition is paired with a release in try/finally in any custom cache code.","Check whether shutdown timing races with active queries; drain queries before shutdown.","Upgrade Druid if the leak originates in known pool-lifecycle bugs in older versions.","Watch the leaked-clients metric; if it grows continuously, restart brokers to reclaim clients and investigate hold durations."],"exampleFix":"// before\nMemcachedClientIF client = pool.get();\nclient.set(key, payload);\n// after\nMemcachedClientIF client = pool.get();\ntry {\n  client.set(key, payload);\n} finally {\n  pool.checkIn(client);\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { MemcachedClientIF c = pool.get(); use(c); } finally { pool.checkIn(c); }","preventionTips":["Always release pooled clients in finally blocks","Drain in-flight queries before shutdown","Track leaked-client metrics and alert on growth"],"tags":["druid","cache","memcached","resource-leak"],"backgroundTag":"resource-not-found","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"}