EllanJiang/GameFramework · error · GameFrameworkException
Reference type is not a non-abstract class type.
Error message
Reference type is not a non-abstract class type.
What it means
ReferencePool requires every pooled type to be a concrete (non-abstract) class, because the pool must be able to instantiate it with new(). InternalCheckReferenceType rejects interface or abstract types with this message on all entry points (Acquire, Release, Add, Remove, RemoveAll).
Solutions
- Use only concrete, instantiable classes implementing IReference for all ReferencePool calls.
- If you have several implementations, register each concrete type separately (Add<ImplA>(n), Add<ImplB>(n)).
- Add a static check or unit test that iterates your registered types and asserts !type.IsAbstract.
Example fix
// before ReferencePool.Add<IReference>(100); // interface type // after ReferencePool.Add<MyConcreteReference>(100); // concrete class implementing IReference
Defensive patterns
Strategy: validation
Validate before calling
System.Diagnostics.Debug.Assert(
typeof(T).IsClass && !typeof(T).IsAbstract,
"ReferencePool requires a concrete class, got: " + typeof(T).FullName); Type guard
static bool IsConcreteClass(Type t) => t != null && t.IsClass && !t.IsAbstract;
Try / catch
try { ReferencePool.Add<T>(count); }
catch (GameFrameworkException ex) when (ex.Message.Contains("non-abstract class"))
{
// T is an interface or abstract class — switch to each concrete implementation
} Prevention
- Pool concrete classes only; never register interfaces or abstract bases.
- Register each implementation of a hierarchy separately if all of them need pooling.
- Constrain generic helpers with 'where T : class, IReference, new()' so the compiler enforces concreteness.
When it happens
Trigger: Calling ReferencePool.Add<T>, Acquire<T>, or Remove<T> where T is an interface (e.g. IReference itself) or an abstract base class of your reference hierarchy.
Common situations: Trying to pre-warm a pool against an interface 'for all implementers' — pooling is per concrete type, not per interface; registering an abstract base in generic pool-initialization loops over a hierarchy.
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 invalid.
- 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/a37d8299ccf766fe.
Report an issue: GitHub.
Appendix: source
Thrown at GameFramework/Base/ReferencePool/ReferencePool.cs:196
InternalCheckReferenceType(referenceType);
GetReferenceCollection(referenceType).RemoveAll();
}
private static void InternalCheckReferenceType(Type referenceType)
{
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)
{View on GitHub (pinned to d0c010b051)