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
- 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.
- Check that every Release call releases the exact type it acquired; cast or inspect the object's runtime type if in doubt.
- 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
- Centralize Acquire/Add/Release for each reference type in one static helper so T can never diverge.
- Never mix base and derived types in the same pool lifecycle.
- Search call sites for typeof()/GetType() uses that could route the wrong Type into the pool.
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
- The reference has been released.
- Reference is invalid.
- Reference type is invalid.
- Reference type is not a non-abstract class type.
- Reference type ' ' is invalid.
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)