{"record":{"id":"de384e1c17a7d230","repo":"apache/cassandra","slug":"attempted-to-reference-an-already-released-sharedb","errorCode":null,"errorMessage":"Attempted to reference an already released SharedByteBuffer","messagePattern":"Attempted to reference an already released SharedByteBuffer","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/net/ShareableBytes.java","lineNumber":113,"sourceCode":"    private ShareableBytes retain()\n    {\n        owner.doRetain();\n        return this;\n    }\n\n    private void doRetain()\n    {\n        int count = this.count;\n        if (count < 0)\n        {\n            countUpdater.lazySet(this, count - 1);\n            return;\n        }\n\n        while (true)\n        {\n            if (count == RELEASED)\n                throw new IllegalStateException(\"Attempted to reference an already released SharedByteBuffer\");\n\n            if (countUpdater.compareAndSet(this, count, count + 1))\n                return;\n\n            count = this.count;\n        }\n    }\n\n    public void release()\n    {\n        owner.doRelease();\n    }\n\n    private void doRelease()\n    {\n        int count = this.count;\n\n        if (count < 0)","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/net/ShareableBytes.java#L95-L131","documentation":"ShareableBytes wraps a buffer with a reference count; doRetain() increments that count in a CAS loop. If the count has already reached the RELEASED sentinel (-1), the buffer can no longer be referenced and retain() throws IllegalStateException.","triggerScenarios":"Calling bytes.retain() (or sharing the buffer) after bytes.release() has dropped the final reference, e.g. retaining a frame buffer in a callback that runs after the connection already released it.","commonSituations":"Async messaging pipelines where a read handler keeps a reference to SharedBytes past the point the connection handler releases it; double-release then retain; races between frame consumer and connection teardown.","solutions":["Fix ownership so each consumer retains before the releaser releases (retain-then-use ordering)","Check bytes.isReleased() before retaining in deferred/async callbacks","Remove the duplicate release that frees the buffer while still in use"],"exampleFix":"// before\nreleaseShared(buffer);\nconsumer.accept(shared); // may retain after release\n// after\nshared.retain(); // take a reference before releasing producer's copy\nreleaseShared(buffer);\nconsumer.accept(shared);","handlingStrategy":"type-guard","validationCode":"if (shared.isReleased()) { /* do not use */ }","typeGuard":"boolean usable(ShareableBytes b) { return b != null && !b.isReleased(); }","tryCatchPattern":"try { shared.retain(); } catch (IllegalStateException e) { log.debug(\"Buffer already released; dropping reference\"); }","preventionTips":["Retain before handing a buffer to async consumers","Establish a single owner responsible for the final release","Check isReleased() in deferred callbacks"],"tags":["network","buffer","reference-counting","concurrency"],"backgroundTag":"invalid-state-transition","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}