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

  1. Inspect the InnerException of the HarmonyException — it holds the actual failure cause
  2. Fix the patch method signature to match the target's parameters (add __instance/__originalMethod/argument params correctly)
  3. Guard TargetMethod()/TargetMethods() against nulls and verify targets with AccessTools before patching
  4. 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

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


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)