{"record":{"id":"3bc8a4beb7ed8114","repo":"apache/druid","slug":"cannot-exceed-pre-configured-maximum-size","errorCode":null,"errorMessage":"Cannot exceed pre-configured maximum size","messagePattern":"Cannot exceed pre-configured maximum size","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/collections/DefaultBlockingPool.java","lineNumber":246,"sourceCode":"      lock.unlock();\n    }\n  }\n\n  private void checkInitialized()\n  {\n    Preconditions.checkState(maxSize > 0, \"Pool was initialized with limit = 0, there are no objects to take.\");\n  }\n\n  private void offer(T theObject)\n  {\n    final ReentrantLock lock = this.lock;\n    lock.lock();\n    try {\n      if (objects.size() < maxSize) {\n        objects.push(theObject);\n        notEnough.signal();\n      } else {\n        throw new ISE(\"Cannot exceed pre-configured maximum size\");\n      }\n    }\n    finally {\n      lock.unlock();\n    }\n  }\n}\n","sourceCodeStart":228,"sourceCodeEnd":254,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/collections/DefaultBlockingPool.java#L228-L254","documentation":"DefaultBlockingPool.offer() returns an object to the pool only when the pool is below maxSize. Exceeding the pre-configured maximum means the pool's invariant (total objects <= maxSize) would be violated, so it throws ISE.","triggerScenarios":"Calling offer() (via wrapObject) when the pool already holds maxSize objects — usually because an object was taken from the pool and offered back more than once, or a foreign object was offered while the pool is full.","commonSituations":"Double release of pooled buffers; pool misuse in custom code sharing DefaultBlockingPool; accounting bugs where taken counters were not decremented.","solutions":["Ensure each taken object is offered back exactly once","Only offer objects that were taken from this pool","Audit code paths that duplicate releases (finally blocks plus explicit release)","Increase maxSize only if the pool legitimately needs more capacity"],"exampleFix":"// before\nT obj = pool.take();\npool.offer(obj); pool.offer(obj); // second offer over full pool -> ISE\n// after\nT obj = pool.take();\ntry { use(obj); } finally { pool.offer(obj); } // exactly once","handlingStrategy":"validation","validationCode":"// offer only objects taken from the pool, exactly once\nif (takenCount > 0 && !returned) { pool.offer(obj); returned = true; }","typeGuard":null,"tryCatchPattern":"try {\n  pool.offer(obj);\n} catch (ISE e) {\n  if (\"Cannot exceed pre-configured maximum size\".equals(e.getMessage())) { /* double-release; drop obj */ }\n  else throw e;\n}","preventionTips":["Use try/finally to guarantee single release","Never offer foreign objects to the pool","Track taken objects to prevent duplicate returns"],"tags":["pooling","resources"],"backgroundTag":"internal-invariant-violation","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"}