EllanJiang/GameFramework · error · GameFrameworkException

The reference has been released.

Error message

The reference has been released.

What it means

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.

Solutions

  1. Find and remove the duplicate Release call — release each acquired reference exactly once, from a single owner.
  2. Null out or mark the field holding the reference after Release so a second release path cannot reach it.
  3. Temporarily keep strict checking enabled during development to catch double-releases early; do not simply disable it to silence the error in production.

Example fix

// before
ReferencePool.Release(reference);
Cleanup(); // Cleanup also calls Release(reference) -> double release

// after
ReferencePool.Release(reference);
reference = null;
Cleanup(); // guard: if (reference != null) Release
Defensive patterns

Strategy: validation

Validate before calling

// keep a released-flag or null the field immediately:
if (reference == null || reference.IsReleased) return; // caller-side bookkeeping
ReferencePool.Release(reference);
reference = null;

Type guard

bool CanRelease<T>(T r) where T : class, IReference => r != null && !releasedTracker.Contains(r);

Try / catch

try { ReferencePool.Release(reference); }
catch (GameFrameworkException ex) when (ex.Message.Contains("has been released"))
{
    // double release — log stack of both release sites; make second release a no-op
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of EllanJiang/GameFramework@d0c010b051 (2026-09-15). Data as JSON: /api/errors/553cba2a9d33dcb6. Report an issue: GitHub.

Appendix: source

Thrown at GameFramework/Base/ReferencePool/ReferencePool.ReferenceCollection.cs:136

                {
                    if (m_References.Count > 0)
                    {
                        return m_References.Dequeue();
                    }
                }

                m_AddReferenceCount++;
                return (IReference)Activator.CreateInstance(m_ReferenceType);
            }

            public void Release(IReference reference)
            {
                reference.Clear();
                lock (m_References)
                {
                    if (m_EnableStrictCheck && m_References.Contains(reference))
                    {
                        throw new GameFrameworkException("The reference has been released.");
                    }

                    m_References.Enqueue(reference);
                }

                m_ReleaseReferenceCount++;
                m_UsingReferenceCount--;
            }

            public void Add<T>(int count) where T : class, IReference, new()
            {
                if (typeof(T) != m_ReferenceType)
                {
                    throw new GameFrameworkException("Type is invalid.");
                }

                lock (m_References)
                {

View on GitHub (pinned to d0c010b051)