EllanJiang/GameFramework · error · GameFrameworkException

Type is invalid.

Error message

Type is invalid.

What it means

ReferencePool stores one ReferenceCollection per concrete IReference type. When Acquire<T>() is called, the nested ReferenceCollection checks that the generic type parameter T exactly matches the collection's stored reference type (m_ReferenceType) before handing out an instance. A mismatch means a reference of a different type was requested from the wrong collection, indicating a pooling bookkeeping bug.

Solutions

  1. Ensure the T passed to ReferencePool.Acquire<T> is exactly the same concrete type that was used with Add<T> and Release — no base/derived mixing.
  2. Check that every Release call releases the exact type it acquired; cast or inspect the object's runtime type if in doubt.
  3. Reproduce with strict checking enabled and log typeof(T) versus the collection's m_ReferenceType at both Acquire and Release sites.

Example fix

// before
MyBaseReference r = ReferencePool.Acquire(typeof(MyDerivedReference)); // type mismatch

// after
MyDerivedReference r = ReferencePool.Acquire<MyDerivedReference>(); // exact type for both Add/Acquire/Release
Defensive patterns

Strategy: type-guard

Validate before calling

// before acquire
Type requested = typeof(T); // must equal the exact type used in Add/Release

Type guard

static bool SamePoolType<T>() where T : class, IReference, new() => typeof(T) == typeof(T); // use one generic helper per concrete reference type so T is fixed at compile time

Try / catch

try { r = ReferencePool.Acquire<T>(); }
catch (GameFrameworkException ex) when (ex.Message == "Type is invalid.")
{
    // log typeof(T) and the Add/Release sites to find the base/derived mix-up
}

Prevention

When it happens

Trigger: Acquire<T>() where typeof(T) differs from the type with which the collection was created — typically reached when ReferencePool.Release stored an object under one type but Acquire<T> resolves another (e.g. derived vs. base type, or two distinct types with similar names), or internal collection lookup returned the wrong bucket.

Common situations: Releasing a derived class instance then acquiring via the base class type (or vice versa); renaming/re-factoring a reference class so stale code acquires the old type; generic helper wrappers that pass a wrong T through to ReferencePool.Acquire.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

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

                get
                {
                    return m_AddReferenceCount;
                }
            }

            public int RemoveReferenceCount
            {
                get
                {
                    return m_RemoveReferenceCount;
                }
            }

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

                m_UsingReferenceCount++;
                m_AcquireReferenceCount++;
                lock (m_References)
                {
                    if (m_References.Count > 0)
                    {
                        return (T)m_References.Dequeue();
                    }
                }

                m_AddReferenceCount++;
                return new T();
            }

            public IReference Acquire()
            {

View on GitHub (pinned to d0c010b051)