{"record":{"id":"51da8863950ff149","repo":"EllanJiang/GameFramework","slug":"referencetype-is-invalid","errorCode":null,"errorMessage":"ReferenceType is invalid.","messagePattern":"ReferenceType is invalid\\.","errorType":"exception","errorClass":"GameFrameworkException","httpStatus":null,"severity":"error","filePath":"GameFramework/Base/ReferencePool/ReferencePool.cs","lineNumber":209,"sourceCode":"                throw new GameFrameworkException(\"Reference type is invalid.\");\n            }\n\n            if (!referenceType.IsClass || referenceType.IsAbstract)\n            {\n                throw new GameFrameworkException(\"Reference type is not a non-abstract class type.\");\n            }\n\n            if (!typeof(IReference).IsAssignableFrom(referenceType))\n            {\n                throw new GameFrameworkException(Utility.Text.Format(\"Reference type '{0}' is invalid.\", referenceType.FullName));\n            }\n        }\n\n        private static ReferenceCollection GetReferenceCollection(Type referenceType)\n        {\n            if (referenceType == null)\n            {\n                throw new GameFrameworkException(\"ReferenceType is invalid.\");\n            }\n\n            ReferenceCollection referenceCollection = null;\n            lock (s_ReferenceCollections)\n            {\n                if (!s_ReferenceCollections.TryGetValue(referenceType, out referenceCollection))\n                {\n                    referenceCollection = new ReferenceCollection(referenceType);\n                    s_ReferenceCollections.Add(referenceType, referenceCollection);\n                }\n            }\n\n            return referenceCollection;\n        }\n    }\n}\n","sourceCodeStart":191,"sourceCodeEnd":226,"githubUrl":"https://github.com/EllanJiang/GameFramework/blob/d0c010b05167c58e92350449d04864a91ca13fd2/GameFramework/Base/ReferencePool/ReferencePool.cs#L191-L226","documentation":"GetReferenceCollection resolves (and lazily creates) the ReferenceCollection for a given reference type. Although callers upstream already validated the type, this private helper re-checks for null as an internal invariant; a null here means the validation chain was bypassed or broken. It is reached from Acquire, Release, Add, Remove, and RemoveAll.","triggerScenarios":"An internal-invariant failure: InternalCheckReferenceType would normally reject a null type before GetReferenceCollection runs, so hitting this throw implies a new code path called GetReferenceCollection directly or the validation logic changed — essentially unreachable through the public API unless the framework is modified.","commonSituations":"Custom forks or patched builds of ReferencePool that skip InternalCheckReferenceType; new overloads added by the team calling GetReferenceCollection without prior validation.","solutions":["Ensure every path that resolves a collection calls InternalCheckReferenceType (or passes a non-null type) first.","In a forked/modified ReferencePool, restore the validation call before GetReferenceCollection.","If this fires in stock GameFramework, treat it as a bug and inspect the modified source of ReferencePool.cs."],"exampleFix":"// before (custom overload)\nprivate static void Remove(Type referenceType)\n{\n    GetReferenceCollection(referenceType).Remove(); // null type slips through\n}\n\n// after\nprivate static void Remove(Type referenceType)\n{\n    InternalCheckReferenceType(referenceType);\n    GetReferenceCollection(referenceType).Remove();\n}","handlingStrategy":"try-catch","validationCode":"// only relevant when patching the framework:\nInternalCheckReferenceType(referenceType); // must precede GetReferenceCollection\n","typeGuard":"bool Resolvable(Type t) => t != null && typeof(IReference).IsAssignableFrom(t) && t.IsClass && !t.IsAbstract;","tryCatchPattern":"try { ReferencePool.Acquire<T>(); }\ncatch (GameFrameworkException ex) when (ex.Message == \"ReferenceType is invalid.\")\n{\n    // invariant broken — audit custom code paths into ReferencePool internals\n}","preventionTips":["Do not call private internals of ReferencePool from custom overloads; route through the validated public API.","If you fork the framework, keep the InternalCheckReferenceType call before every GetReferenceCollection use.","Keep the public generic API as the only entry point to pooling in application code."],"tags":["object-pool","internal-invariant","null-argument","reference-pool"],"backgroundTag":"internal-invariant-violation","analyzedSha":"d0c010b05167c58e92350449d04864a91ca13fd2","analyzedAt":"2026-09-15T13:37:15.352Z","contentChangedAt":"2026-09-15T13:37:15.352Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}