{"record":{"id":"76c085e4e495638b","repo":"pardeike/Harmony","slug":"patching-exception-in-method-original-fulldescription","errorCode":null,"errorMessage":"Patching exception in method {original.FullDescription()}","messagePattern":"Patching exception in method (.+?)","errorType":"exception","errorClass":"HarmonyException","httpStatus":null,"severity":"error","filePath":"Harmony/Public/PatchClassProcessor.cs","lineNumber":314,"sourceCode":"\t\t\t\t_ = Harmony.VersionInfo(out var currentVersion);\r\n\r\n\t\t\t\tFileLog.indentLevel = 0;\r\n\t\t\t\tFileLog.Log($\"### Exception from user \\\"{instance.Id}\\\", Harmony v{currentVersion}\");\r\n\t\t\t\tFileLog.Log($\"### Original: {(original?.FullDescription() ?? \"NULL\")}\");\r\n\t\t\t\tFileLog.Log($\"### Patch class: {containerType.FullDescription()}\");\r\n\t\t\t\tvar logException = exception;\r\n\t\t\t\tif (logException is HarmonyException hEx)\r\n\t\t\t\t\tlogException = hEx.InnerException;\r\n\t\t\t\tvar exStr = logException.ToString();\r\n\t\t\t\twhile (exStr.Contains(\"\\n\\n\"))\r\n\t\t\t\t\texStr = exStr.Replace(\"\\n\\n\", \"\\n\");\r\n\t\t\t\texStr = exStr.Split('\\n').Join(line => $\"### {line}\", \"\\n\");\r\n\t\t\t\tFileLog.Log(exStr.Trim());\r\n\t\t\t}\r\n\r\n\t\t\tif (exception is HarmonyException)\r\n\t\t\t\tthrow exception; // assume HarmonyException already wraps the actual exception\r\n\t\t\tthrow new HarmonyException($\"Patching exception in method {original.FullDescription()}\", exception);\r\n\t\t}\r\n\r\n\t\t[SuppressMessage(\"Style\", \"IDE0300\")]\r\n\t\tT RunMethod<S, T>(T defaultIfNotExisting, T defaultIfFailing, Func<T, string> failOnResult = null, params object[] parameters)\r\n\t\t{\r\n\t\t\tif (auxilaryMethods.TryGetValue(typeof(S), out var method))\r\n\t\t\t{\r\n\t\t\t\tvar input = (parameters ?? []).Union(new object[] { instance }).ToArray();\r\n\t\t\t\tvar actualParameters = AccessTools.ActualParameters(method, input);\r\n\r\n\t\t\t\tif (method.ReturnType != typeof(void) && typeof(T).IsAssignableFrom(method.ReturnType) is false)\r\n\t\t\t\t\tthrow new Exception($\"Method {method.FullDescription()} has wrong return type (should be assignable to {typeof(T).FullName})\");\r\n\r\n\t\t\t\tvar result = defaultIfFailing;\r\n\t\t\t\ttry\r\n\t\t\t\t{\r\n\t\t\t\t\tif (method.ReturnType == typeof(void))\r\n\t\t\t\t\t{\r","sourceCodeStart":296,"sourceCodeEnd":332,"githubUrl":"https://github.com/pardeike/Harmony/blob/e7872dc17008bc0ca2b3de1f53fd4120dbd7a17c/Harmony/Public/PatchClassProcessor.cs#L296-L332","documentation":"ReportException is Harmony's central error funnel during patching. When a non-HarmonyException failure occurs while processing a patch job (in Patch, ProcessPatchJob, or RunMethod), Harmony wraps the original exception in a HarmonyException whose message names the target method being patched, preserving the inner exception as the real cause.","triggerScenarios":"Any exception thrown during PatchClassProcessor.Patch/Unpatch while building or applying the replacement method: failed target resolution, patch-method binding errors, IL emission failures, exceptions inside TargetMethod/TargetMethods helpers.","commonSituations":"Target method signatures changed between versions so postfixes/prefixes no longer bind; wrong parameter types in patch methods; AccessTools lookups returning null inside TargetMethod(); IL transpiler bugs.","solutions":["Inspect the InnerException of the HarmonyException — it holds the actual failure cause","Fix the patch method signature to match the target's parameters (add __instance/__originalMethod/argument params correctly)","Guard TargetMethod()/TargetMethods() against nulls and verify targets with AccessTools before patching","Set Harmony.DEBUG (FileLog) to get the full annotated stack of the patching failure"],"exampleFix":"// before\nstatic void Postfix(int wrongName) { }\n// after\ntry { harmony.PatchAll(); }\ncatch (HarmonyException e) { Logger.Log(e.InnerException); throw; }\n// and fix the patch signature:\nstatic void Postfix(Player __instance, Vector3 target) { }","handlingStrategy":"try-catch","validationCode":"// pre-validate targets\nforeach (var t in CollectTargets()) if (AccessTools.Method(t.type, t.name, t.args) == null) Warn(t);","typeGuard":null,"tryCatchPattern":"try { harmony.PatchAll(); }\ncatch (HarmonyException e)\n{\n    log.LogError($\"Patch failed for {e.Message}\");\n    log.LogError(e.InnerException);\n}","preventionTips":["Always read HarmonyException.InnerException for the real cause","Enable Harmony.DEBUG/FileLog during development to see patch-build details","Keep patch method parameter names/types in sync with the target signature (use __0, __instance, __originalMethod)","Re-run patches after any dependency/game update that changes target signatures"],"tags":["patching-failed","wrapped-exception","harmony","csharp"],"backgroundTag":"internal-invariant-violation","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"}