pardeike/Harmony · error · NullReferenceException

Null method for

Error message

Null method for {instance.Id}

What it means

ReversePatcher.Patch() creates a stand-alone copy of an original (unpatched) method body via a reverse transpiler. It requires a valid original MethodInfo; when the standin/original is null it throws a NullReferenceException with the Harmony instance id.

Solutions

  1. Fix the method lookup so a valid original MethodInfo is passed to CreateReversePatcher
  2. Null-check the MethodInfo before creating the ReversePatcher
  3. Confirm the target method still exists and is a normal (non-abstract) method in the current target version

Example fix

// before
var patcher = harmony.CreateReversePatcher(AccessTools.Method(typeof(Player), "Original"));
var unpatched = patcher.Patch();
// after
var original = AccessTools.Method(typeof(Player), "Original");
if (original is null) throw new Exception("Player.Original not found");
var unpatched = harmony.CreateReversePatcher(original).Patch();
Defensive patterns

Strategy: validation

Validate before calling

var original = AccessTools.Method(targetType, methodName);
if (original is null)
    throw new InvalidOperationException($"Reverse patch target {targetType}.{methodName} not found");

Try / catch

try { var unpatched = reversePatcher.Patch(); }
catch (NullReferenceException ex) when (ex.Message.StartsWith("Null method for")) { logger.Error("Reverse patch target unresolved"); }

Prevention

When it happens

Trigger: Calling Patch() on a ReversePatcher created with a null original — e.g. harmony.CreateReversePatcher(AccessTools.Method(...) that returned null, or GetMethod called on a null standin method).

Common situations: Unpatching-by-reverse-patching after a target lookup failed due to a typo or an updated target assembly where the method was renamed or moved.

Related errors


AI-assisted analysis of pardeike/Harmony@e7872dc170 (2026-09-15). Data as JSON: /api/errors/6c44a32c8e99e199. Report an issue: GitHub.

Appendix: source

Thrown at Harmony/Public/ReversePatcher.cs:35

		/// <param name="instance">The Harmony instance</param>
		/// <param name="original">The original method/constructor</param>
		/// <param name="standin">Your stand-in stub method as <see cref="HarmonyMethod"/></param>
		///
		public ReversePatcher(Harmony instance, MethodBase original, HarmonyMethod standin)
		{
			this.instance = instance;
			this.original = original;
			this.standin = standin;
		}

		/// <summary>Applies the patch</summary>
		/// <param name="type">The type of patch, see <see cref="HarmonyReversePatchType"/></param>
		/// <returns>The generated replacement method</returns>
		///
		public MethodInfo Patch(HarmonyReversePatchType type = HarmonyReversePatchType.Original)
		{
			if (original is null)
				throw new NullReferenceException($"Null method for {instance.Id}");

			standin.reversePatchType = type;
			var transpiler = GetTranspiler(standin.method);
			return PatchFunctions.ReversePatch(standin, original, transpiler);
		}

		internal static MethodInfo GetTranspiler(MethodInfo method)
		{
			var methodName = method.Name;
			var type = method.DeclaringType;
			var methods = AccessTools.GetDeclaredMethods(type);
			var ici = typeof(IEnumerable<CodeInstruction>);
			return methods.FirstOrDefault(m =>
			{
				if (m.ReturnType != ici)
					return false;
				return m.Name.StartsWith($"<{methodName}>");
			});

View on GitHub (pinned to e7872dc170)