{"record":{"id":"553cba2a9d33dcb6","repo":"EllanJiang/GameFramework","slug":"the-reference-has-been-released","errorCode":null,"errorMessage":"The reference has been released.","messagePattern":"The reference has been released\\.","errorType":"exception","errorClass":"GameFrameworkException","httpStatus":null,"severity":"error","filePath":"GameFramework/Base/ReferencePool/ReferencePool.ReferenceCollection.cs","lineNumber":136,"sourceCode":"                {\n                    if (m_References.Count > 0)\n                    {\n                        return m_References.Dequeue();\n                    }\n                }\n\n                m_AddReferenceCount++;\n                return (IReference)Activator.CreateInstance(m_ReferenceType);\n            }\n\n            public void Release(IReference reference)\n            {\n                reference.Clear();\n                lock (m_References)\n                {\n                    if (m_EnableStrictCheck && m_References.Contains(reference))\n                    {\n                        throw new GameFrameworkException(\"The reference has been released.\");\n                    }\n\n                    m_References.Enqueue(reference);\n                }\n\n                m_ReleaseReferenceCount++;\n                m_UsingReferenceCount--;\n            }\n\n            public void Add<T>(int count) where T : class, IReference, new()\n            {\n                if (typeof(T) != m_ReferenceType)\n                {\n                    throw new GameFrameworkException(\"Type is invalid.\");\n                }\n\n                lock (m_References)\n                {","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/EllanJiang/GameFramework/blob/d0c010b05167c58e92350449d04864a91ca13fd2/GameFramework/Base/ReferencePool/ReferencePool.ReferenceCollection.cs#L118-L154","documentation":"ReferencePool.ReferenceCollection.Release returns a reference to the pool for reuse. With strict checking enabled (m_EnableStrictCheck), the collection verifies the reference is not already sitting in its free list before enqueueing; if it is, the same reference was released twice, and the framework throws rather than corrupting the pool with a duplicate entry that could be handed out to two owners.","triggerScenarios":"Calling ReferencePool.Release(reference) twice for the same instance — e.g. both the owner and a cleanup routine release it, or a double-dispose path (explicit release plus a parent/manager release) — while ReferencePool.EnableStrictCheck is true.","commonSituations":"Double-free bugs in entity/component lifecycles where both the spawner and the scene teardown call Release; exception paths that release a reference and then a finally block releases it again; clear-all logic that releases references still tracked elsewhere.","solutions":["Find and remove the duplicate Release call — release each acquired reference exactly once, from a single owner.","Null out or mark the field holding the reference after Release so a second release path cannot reach it.","Temporarily keep strict checking enabled during development to catch double-releases early; do not simply disable it to silence the error in production."],"exampleFix":"// before\nReferencePool.Release(reference);\nCleanup(); // Cleanup also calls Release(reference) -> double release\n\n// after\nReferencePool.Release(reference);\nreference = null;\nCleanup(); // guard: if (reference != null) Release","handlingStrategy":"validation","validationCode":"// keep a released-flag or null the field immediately:\nif (reference == null || reference.IsReleased) return; // caller-side bookkeeping\nReferencePool.Release(reference);\nreference = null;","typeGuard":"bool CanRelease<T>(T r) where T : class, IReference => r != null && !releasedTracker.Contains(r);","tryCatchPattern":"try { ReferencePool.Release(reference); }\ncatch (GameFrameworkException ex) when (ex.Message.Contains(\"has been released\"))\n{\n    // double release — log stack of both release sites; make second release a no-op\n}","preventionTips":["Null the reference field immediately after Release so cleanup paths cannot release it twice.","Assign a single owner responsible for releasing each pooled reference.","Keep EnableStrictCheck on in development builds to surface double-releases early."],"tags":["object-pool","double-release","reference-pool","lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"d0c010b05167c58e92350449d04864a91ca13fd2","analyzedAt":"2026-09-15T13:37:15.352Z","contentChangedAt":"2026-09-15T13:37:15.352Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}