EllanJiang/GameFramework · error · GameFrameworkException
Reference type ' ' is invalid.
Error message
Reference type '{0}' is invalid. What it means
After confirming the type is a non-abstract class, InternalCheckReferenceType verifies the type actually implements IReference. A type that is a valid class but does not implement the pooling interface cannot be tracked or cleared by the pool, so it is rejected with a message naming the offending type's full name.
Solutions
- Make the pooled class implement the framework's IReference interface (implementing Clear() as required).
- Confirm there is only one IReference type in scope — remove stale/duplicate interface definitions from other framework copies.
- If the class cannot implement IReference, use a different pooling mechanism instead of ReferencePool.
Example fix
// before
public class DamageInfo { public int Amount; } // no IReference
// after
public class DamageInfo : IReference
{
public int Amount;
public void Clear() { Amount = 0; }
} Defensive patterns
Strategy: type-guard
Validate before calling
System.Diagnostics.Debug.Assert(
typeof(IReference).IsAssignableFrom(typeof(T)),
typeof(T).FullName + " must implement IReference before pooling."); Type guard
static bool ImplementsIReference(Type t) => typeof(IReference).IsAssignableFrom(t) && t.IsClass && !t.IsAbstract;
Try / catch
try { ReferencePool.Acquire<T>(); }
catch (GameFrameworkException ex) when (ex.Message.Contains("is invalid") && ex.Message.Contains(typeof(T).Name))
{
// T does not implement IReference — add the interface or use another pool
} Prevention
- Make every pooled class implement IReference and its Clear() method from day one.
- Remove duplicate IReference definitions when consolidating framework copies to avoid 'implements the wrong IReference' bugs.
- Add a reflection-based startup check that all types marked [Poolable] implement IReference.
When it happens
Trigger: Calling ReferencePool.Acquire<T>/Add<T>/Release/Remove with a plain class (one that implements neither IReference nor a derived interface) — often a POCO, a struct-wrapped class, or a class implementing a similarly named custom interface.
Common situations: Refactoring that moved IReference to a different namespace and left the class implementing an old/shim interface; pooling a third-party or data class that was never meant for ReferencePool; using two different IReference interfaces from different framework versions in the same project.
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
- Reference type is invalid.
- Reference type is not a non-abstract class type.
- Type is invalid.
- The reference has been released.
- Reference is invalid.
AI-assisted analysis of EllanJiang/GameFramework@d0c010b051 (2026-09-15).
Data as JSON: /api/errors/346f8874e79b4c63.
Report an issue: GitHub.
Appendix: source
Thrown at GameFramework/Base/ReferencePool/ReferencePool.cs:201
{
if (!m_EnableStrictCheck)
{
return;
}
if (referenceType == null)
{
throw new GameFrameworkException("Reference type is invalid.");
}
if (!referenceType.IsClass || referenceType.IsAbstract)
{
throw new GameFrameworkException("Reference type is not a non-abstract class type.");
}
if (!typeof(IReference).IsAssignableFrom(referenceType))
{
throw new GameFrameworkException(Utility.Text.Format("Reference type '{0}' is invalid.", referenceType.FullName));
}
}
private static ReferenceCollection GetReferenceCollection(Type referenceType)
{
if (referenceType == null)
{
throw new GameFrameworkException("ReferenceType is invalid.");
}
ReferenceCollection referenceCollection = null;
lock (s_ReferenceCollections)
{
if (!s_ReferenceCollections.TryGetValue(referenceType, out referenceCollection))
{
referenceCollection = new ReferenceCollection(referenceType);
s_ReferenceCollections.Add(referenceType, referenceCollection);
}View on GitHub (pinned to d0c010b051)