pardeike/Harmony · error · HarmonyException
Patching exception in method
Error message
Patching exception in method {original.FullDescription()} What it means
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.
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
Example fix
// before
static void Postfix(int wrongName) { }
// after
try { harmony.PatchAll(); }
catch (HarmonyException e) { Logger.Log(e.InnerException); throw; }
// and fix the patch signature:
static void Postfix(Player __instance, Vector3 target) { } Defensive patterns
Strategy: try-catch
Validate before calling
// pre-validate targets foreach (var t in CollectTargets()) if (AccessTools.Method(t.type, t.name, t.args) == null) Warn(t);
Try / catch
try { harmony.PatchAll(); }
catch (HarmonyException e)
{
log.LogError($"Patch failed for {e.Message}");
log.LogError(e.InnerException);
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- cannot contain zeros
- Cannot directly reference dynamic method \
- [ ]
- Method has wrong return type (should be assignable to )
- Null method for
AI-assisted analysis of pardeike/Harmony@e7872dc170 (2026-09-15).
Data as JSON: /api/errors/76c085e4e495638b.
Report an issue: GitHub.
Appendix: source
Thrown at Harmony/Public/PatchClassProcessor.cs:314
_ = Harmony.VersionInfo(out var currentVersion);
FileLog.indentLevel = 0;
FileLog.Log($"### Exception from user \"{instance.Id}\", Harmony v{currentVersion}");
FileLog.Log($"### Original: {(original?.FullDescription() ?? "NULL")}");
FileLog.Log($"### Patch class: {containerType.FullDescription()}");
var logException = exception;
if (logException is HarmonyException hEx)
logException = hEx.InnerException;
var exStr = logException.ToString();
while (exStr.Contains("\n\n"))
exStr = exStr.Replace("\n\n", "\n");
exStr = exStr.Split('\n').Join(line => $"### {line}", "\n");
FileLog.Log(exStr.Trim());
}
if (exception is HarmonyException)
throw exception; // assume HarmonyException already wraps the actual exception
throw new HarmonyException($"Patching exception in method {original.FullDescription()}", exception);
}
[SuppressMessage("Style", "IDE0300")]
T RunMethod<S, T>(T defaultIfNotExisting, T defaultIfFailing, Func<T, string> failOnResult = null, params object[] parameters)
{
if (auxilaryMethods.TryGetValue(typeof(S), out var method))
{
var input = (parameters ?? []).Union(new object[] { instance }).ToArray();
var actualParameters = AccessTools.ActualParameters(method, input);
if (method.ReturnType != typeof(void) && typeof(T).IsAssignableFrom(method.ReturnType) is false)
throw new Exception($"Method {method.FullDescription()} has wrong return type (should be assignable to {typeof(T).FullName})");
var result = defaultIfFailing;
try
{
if (method.ReturnType == typeof(void))
{
View on GitHub (pinned to e7872dc170)