{"record":{"id":"64c1580691ef6585","repo":"EllanJiang/GameFramework","slug":"try-get-value-callback-is-invalid","errorCode":null,"errorMessage":"Try get value callback is invalid.","messagePattern":"Try get value callback is invalid\\.","errorType":"exception","errorClass":"GameFrameworkException","httpStatus":null,"severity":"error","filePath":"GameFramework/Base/GameFrameworkSerializer.cs","lineNumber":105,"sourceCode":"                throw new GameFrameworkException(\"Deserialize callback is invalid.\");\n            }\n\n            m_DeserializeCallbacks[version] = callback;\n        }\n\n        /// <summary>\n        /// 注册尝试从指定流获取指定键的值回调函数。\n        /// </summary>\n        /// <param name=\"version\">尝试从指定流获取指定键的值回调函数的版本。</param>\n        /// <param name=\"callback\">尝试从指定流获取指定键的值回调函数。</param>\n        public void RegisterTryGetValueCallback(byte version, TryGetValueCallback callback)\n        {\n            if (callback == null)\n            {\n                throw new GameFrameworkException(\"Try get value callback is invalid.\");\n            }\n\n            m_TryGetValueCallbacks[version] = callback;\n        }\n\n        /// <summary>\n        /// 序列化数据到目标流中。\n        /// </summary>\n        /// <param name=\"stream\">目标流。</param>\n        /// <param name=\"data\">要序列化的数据。</param>\n        /// <returns>是否序列化数据成功。</returns>\n        public bool Serialize(Stream stream, T data)\n        {\n            if (m_SerializeCallbacks.Count <= 0)\n            {\n                throw new GameFrameworkException(\"No serialize callback registered.\");\n            }\n\n            return Serialize(stream, data, m_LatestSerializeCallbackVersion);\n        }\n","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/EllanJiang/GameFramework/blob/d0c010b05167c58e92350449d04864a91ca13fd2/GameFramework/Base/GameFrameworkSerializer.cs#L87-L123","documentation":"GameFrameworkSerializer<T> supports optional 'try get value' callbacks used during deserialization helpers. RegisterTryGetValueCallback throws when the callback parameter is null, since registering nothing would leave a broken entry in the callback table.","triggerScenarios":"Calling serializer.RegisterTryGetValueCallback(version, null), commonly because the delegate expression evaluated to null (missing method, failed factory, config-driven lookup).","commonSituations":"Refactoring removed the TryGetValue handler while registration remained; dynamic registration from reflection where the method wasn't found; copy-paste of register blocks with a placeholder null.","solutions":["Pass a valid non-null TryGetValueCallback delegate for the version.","Verify the resolved delegate is non-null before calling RegisterTryGetValueCallback.","Fix the factory/reflection lookup that produced the null callback.","Only register this optional callback when you actually have an implementation."],"exampleFix":"// before\nserializer.RegisterTryGetValueCallback(1, null);\n// after\nserializer.RegisterTryGetValueCallback(1, (Stream stream, out object value) =>\n{\n    value = reader.ReadInt32();\n    return true;\n});","handlingStrategy":"validation","validationCode":"if (callback == null) { throw new InvalidOperationException(\"TryGetValue callback required.\"); }\nserializer.RegisterTryGetValueCallback(version, callback);","typeGuard":"static bool IsValidCallback(GameFrameworkSerializer<T>.TryGetValueCallback cb) => cb != null;","tryCatchPattern":"try { serializer.RegisterTryGetValueCallback(version, callback); } catch (GameFrameworkException) { /* log null callback registration attempt */ }","preventionTips":["Only register when an implementation exists","Null-check results of reflection-based handler lookup","Keep register calls adjacent to handler definitions"],"tags":["csharp","null-argument","serialization","callback"],"backgroundTag":"null-argument","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"}