{"record":{"id":"389b049652682198","repo":"pardeike/Harmony","slug":"null-method-for-instance-id","errorCode":null,"errorMessage":"Null method for {instance.Id}","messagePattern":"Null method for (.+?)","errorType":"exception","errorClass":"NullReferenceException","httpStatus":null,"severity":"error","filePath":"Harmony/Public/PatchProcessor.cs","lineNumber":172,"sourceCode":"\r\n\t\t/// <summary>Gets all patched original methods in the appdomain</summary>\r\n\t\t/// <returns>An enumeration of patched method/constructor</returns>\r\n\t\t///\r\n\t\tpublic static IEnumerable<MethodBase> GetAllPatchedMethods()\r\n\t\t{\r\n\t\t\tlock (locker)\r\n\t\t\t{\r\n\t\t\t\treturn HarmonySharedState.GetPatchedMethods();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t/// <summary>Applies all registered patches</summary>\r\n\t\t/// <returns>The generated replacement method</returns>\r\n\t\t///\r\n\t\tpublic MethodInfo Patch()\r\n\t\t{\r\n\t\t\tif (original is null)\r\n\t\t\t\tthrow new NullReferenceException($\"Null method for {instance.Id}\");\r\n\r\n\t\t\tif (original.IsDeclaredMember() is false)\r\n\t\t\t{\r\n\t\t\t\tvar declaredMember = original.GetDeclaredMember();\r\n\t\t\t\tthrow new ArgumentException($\"You can only patch implemented methods/constructors. Patch the declared method {declaredMember.FullDescription()} instead.\");\r\n\t\t\t}\r\n\r\n\t\t\tlock (locker)\r\n\t\t\t{\r\n\t\t\t\tvar patchInfo = HarmonySharedState.GetPatchInfo(original) ?? new PatchInfo();\r\n\r\n\t\t\t\tpatchInfo.AddPrefixes(instance.Id, prefix);\r\n\t\t\t\tpatchInfo.AddPostfixes(instance.Id, postfix);\r\n\t\t\t\tpatchInfo.AddTranspilers(instance.Id, transpiler);\r\n\t\t\t\tpatchInfo.AddFinalizers(instance.Id, finalizer);\r\n\t\t\t\tpatchInfo.AddInnerPrefixes(instance.Id, innerprefix);\r\n\t\t\t\tpatchInfo.AddInnerPostfixes(instance.Id, innerpostfix);\r\n\r","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/pardeike/Harmony/blob/e7872dc17008bc0ca2b3de1f53fd4120dbd7a17c/Harmony/Public/PatchProcessor.cs#L154-L190","documentation":"PatchProcessor.Patch() requires an original target method to patch. If the processor was constructed with a null MethodInfo (original), it throws a NullReferenceException including the Harmony instance id. Harmony cannot generate a replacement without a target.","triggerScenarios":"Constructing a PatchProcessor (directly or via Harmony.Patch) with a null original MethodInfo, then calling Patch(). Typically the result of a failed AccessTools.Method/Type search passed straight through without a null check.","commonSituations":"AccessTools.Method(\"TypeName\", \"MethodName\") returns null because the type or method name is misspelled, the method was renamed in a game/library update, or the type failed to load — the null is then fed into Harmony.Patch.","solutions":["Fix the lookup expression so AccessTools returns the actual MethodInfo instead of null","Null-check the MethodInfo returned by AccessTools before calling Harmony.Patch and fail with a clear message","Verify the target type/method still exists in the current version of the patched assembly"],"exampleFix":"// before\nharmony.Patch(AccessTools.Method(typeof(Player), \"Update\"), prefix: new HarmonyMethod(typeof(MyPatch), nameof(MyPatch.Prefix)));\n// after\nvar original = AccessTools.Method(typeof(Player), \"Update\");\nif (original is null) throw new Exception(\"Player.Update not found\");\nharmony.Patch(original, prefix: new HarmonyMethod(typeof(MyPatch), nameof(MyPatch.Prefix)));","handlingStrategy":"validation","validationCode":"var original = AccessTools.Method(targetType, methodName);\nif (original is null)\n    throw new InvalidOperationException($\"Patch target {targetType}.{methodName} not found\");","typeGuard":null,"tryCatchPattern":"try { harmony.Patch(original, prefix: prefix); }\ncatch (NullReferenceException ex) when (ex.Message.StartsWith(\"Null method for\")) { logger.Error($\"Patch target unresolved: {ex.Message}\"); }","preventionTips":["Never pass AccessTools results directly into Patch without a null check","Use nameof() instead of string literals where possible so renames break at compile time","Log the assembly version of the target type when a lookup fails"],"tags":["csharp","reflection","null-reference","harmony"],"backgroundTag":"null-argument","analyzedSha":"e7872dc17008bc0ca2b3de1f53fd4120dbd7a17c","analyzedAt":"2026-09-15T22:47:11.550Z","contentChangedAt":"2026-09-15T22:47:11.550Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}