EllanJiang/GameFramework · error · GameFrameworkException

Reference type is invalid.

Error message

Reference type is invalid.

What it means

ReferencePool.InternalCheckReferenceType validates a Type before a collection is created or looked up for it. If the Type itself is null, the framework cannot key any collection on it and throws 'Reference type is invalid.' This is the first of several type validation gates applied on every Acquire, Release, Add, Remove, and RemoveAll call.

Solutions

  1. Fix the code that produced the null Type — check Type.GetType results for null before passing them to ReferencePool.
  2. Use the generic APIs (Acquire<T>, Add<T>, Remove<T>) where possible so the compiler guarantees a non-null type.
  3. Verify the assembly containing the reference class is loaded and the type name string is fully qualified and correct.

Example fix

// before
var type = Type.GetType("Game.MyReference"); // null on typo/missing assembly
ReferencePool.Add(type, 10);

// after
var type = typeof(Game.MyReference);
ReferencePool.Add(type, 10);
Defensive patterns

Strategy: validation

Validate before calling

if (type == null)
{
    throw new ArgumentException("Reference type name could not be resolved.", nameof(type));
}
ReferencePool.Add(type, count);

Type guard

bool IsValidPoolType(Type t) => t != null;

Try / catch

var type = Type.GetType(typeName);
if (type == null)
{
    // fail fast with the bad type name before touching the pool
    throw new TypeLoadException("Unknown reference type: " + typeName);
}
try { ReferencePool.Add(type, count); }
catch (GameFrameworkException ex) when (ex.Message == "Reference type is invalid.") { /* log typeName */ }

Prevention

When it happens

Trigger: Reaching InternalCheckReferenceType with a null Type — possible via non-generic overloads (e.g. Release(IReference) paths that call GetType() on a null is prevented earlier, but reflection-based or Type-passing overloads like Acquire(Type)/Add(Type,...) can pass null), usually from misconfigured reflection or a failed type lookup.

Common situations: Reflection-driven pooling where Type.GetType("Namespace.Class") returns null due to a typo or missing assembly; configuration-driven pool warm-up that stores type names and resolves them at startup; generic wrappers caching a Type that was never resolved.

Related errors


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

Appendix: source

Thrown at GameFramework/Base/ReferencePool/ReferencePool.cs:191

        /// 从引用池中移除所有的引用。
        /// </summary>
        /// <param name="referenceType">引用类型。</param>
        public static void RemoveAll(Type referenceType)
        {
            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.");

View on GitHub (pinned to d0c010b051)