{"record":{"id":"47e9e34625ab0b14","repo":"egametang/ET","slug":"methodhook-targetmethod-and-replacementmethod-and","errorCode":null,"errorMessage":"MethodHook:targetMethod and replacementMethod and proxyMethod can not be null","messagePattern":"MethodHook:targetMethod and replacementMethod and proxyMethod can not be null","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.hybridclr/Scripts/Editor/Share/3rds/UnityHook/MethodHook.cs","lineNumber":188,"sourceCode":"                    CreateCodePatcher();\n                    _codePatcher.ApplyPatch();\n\n#if ENABLE_HOOK_DEBUG\n                    UnityEngine.Debug.Log($\"New [{targetMethod.DeclaringType.Name}.{targetMethod.Name}]: {HookUtils.HexToString(_targetPtr.ToPointer(), 64, -16)}\");\n                    UnityEngine.Debug.Log($\"New [{replacementMethod.DeclaringType.Name}.{replacementMethod.Name}]: {HookUtils.HexToString(_replacementPtr.ToPointer(), 64, -16)}\");\n                    if(proxyMethod != null)\n                        UnityEngine.Debug.Log($\"New [{proxyMethod.DeclaringType.Name}.{proxyMethod.Name}]: {HookUtils.HexToString(_proxyPtr.ToPointer(), 64, -16)}\");\n#endif\n                }\n            }\n\n            isHooked = true;\n        }\n\n        private void CheckMethod()\n        {\n            if (targetMethod == null || replacementMethod == null)\n                throw new Exception(\"MethodHook:targetMethod and replacementMethod and proxyMethod can not be null\");\n\n            string methodName = $\"{targetMethod.DeclaringType.Name}.{targetMethod.Name}\";\n            if (targetMethod.IsAbstract)\n                throw new Exception($\"WRANING: you can not hook abstract method [{methodName}]\");\n\n#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER\n            int minMethodBodySize = 10;\n\n            {\n                if ((targetMethod.MethodImplementationFlags & MethodImplAttributes.InternalCall) != MethodImplAttributes.InternalCall)\n                {\n                    int codeSize = targetMethod.GetMethodBody().GetILAsByteArray().Length; // GetMethodBody can not call on il2cpp\n                    if (codeSize < minMethodBodySize)\n                        UnityEngine.Debug.LogWarning($\"WRANING: you can not hook method [{methodName}], cause its method body is too short({codeSize}), will random crash on IL2CPP release mode\");\n                }\n            }\n\n            if(proxyMethod != null)","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.hybridclr/Scripts/Editor/Share/3rds/UnityHook/MethodHook.cs#L170-L206","documentation":"Thrown by MethodHook.CheckMethod() when targetMethod or replacementMethod is null. This is a pre-installation validation method (note the message also mentions proxyMethod but the code only checks target and replacement — the message is imprecise). CheckMethod is called to validate the hook configuration before proceeding with installation.","triggerScenarios":"CheckMethod() is invoked on a MethodHook where targetMethod or replacementMethod is null. The trigger is the same root cause as error 170: a failed reflection lookup left one of the required MethodInfo fields null.","commonSituations":"Same as 170: method renamed, wrong BindingFlags, signature mismatch on overloaded methods, assembly not loaded, or a typo in the method name string. The difference is this fires from the explicit CheckMethod path rather than DoInstall.","solutions":["Inspect which MethodInfo is null by logging targetMethod, replacementMethod before calling CheckMethod.","Correct the reflection lookup — verify method name, type, BindingFlags, and parameter types.","Ensure the target assembly is loaded before reflection.","Consider that the message mentions proxyMethod but the check does not test it — do not be misled into only checking proxy."],"exampleFix":"// before\nhook.CheckMethod(); // throws if targetMethod or replacementMethod is null\n\n// after — validate first with a clear diagnostic\nif (targetMethod == null || replacementMethod == null)\n{\n    Debug.LogError($\"Cannot hook: target={targetMethod?.Name ?? \"null\"}, replacement={replacementMethod?.Name ?? \"null\"}\");\n    return;\n}\nhook.CheckMethod();","handlingStrategy":"validation","validationCode":"if (targetMethod == null || replacementMethod == null)\n{\n    Debug.LogError($\"Cannot validate hook: \" +\n        $\"target={targetMethod?.DeclaringType?.Name}.{targetMethod?.Name ?? \"null\"}, \" +\n        $\"replacement={replacementMethod?.DeclaringType?.Name}.{replacementMethod?.Name ?? \"null\"}\");\n    return;\n}","typeGuard":"static bool HasValidMethods(MethodInfo target, MethodInfo replacement)\n{\n    return target != null && replacement != null;\n}","tryCatchPattern":"try\n{\n    hook.CheckMethod();\n}\ncatch (Exception ex) when (ex.Message.Contains(\"can not be null\"))\n{\n    Debug.LogError(\"MethodHook validation failed: a required MethodInfo is null. \" +\n        \"Note: the message mentions proxyMethod but only target and replacement are checked.\");\n}","preventionTips":["Validate all MethodInfo fields are non-null before calling CheckMethod.","Note that the error message mentions proxyMethod but the code only checks target and replacement — do not be misled.","Log the full method identity (type + name + signature) for each field to diagnose which lookup failed.","Add a wrapper that validates and logs before delegating to CheckMethod."],"tags":["unityhook","method-hook","reflection","validation","null-reference"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}