pardeike/Harmony · error · NullReferenceException

Null method for

Error message

Null method for {instance.Id}

What it means

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.

Solutions

  1. Fix the lookup expression so AccessTools returns the actual MethodInfo instead of null
  2. Null-check the MethodInfo returned by AccessTools before calling Harmony.Patch and fail with a clear message
  3. Verify the target type/method still exists in the current version of the patched assembly

Example fix

// before
harmony.Patch(AccessTools.Method(typeof(Player), "Update"), prefix: new HarmonyMethod(typeof(MyPatch), nameof(MyPatch.Prefix)));
// after
var original = AccessTools.Method(typeof(Player), "Update");
if (original is null) throw new Exception("Player.Update not found");
harmony.Patch(original, prefix: new HarmonyMethod(typeof(MyPatch), nameof(MyPatch.Prefix)));
Defensive patterns

Strategy: validation

Validate before calling

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

Try / catch

try { harmony.Patch(original, prefix: prefix); }
catch (NullReferenceException ex) when (ex.Message.StartsWith("Null method for")) { logger.Error($"Patch target unresolved: {ex.Message}"); }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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

Appendix: source

Thrown at Harmony/Public/PatchProcessor.cs:172

		/// <summary>Gets all patched original methods in the appdomain</summary>
		/// <returns>An enumeration of patched method/constructor</returns>
		///
		public static IEnumerable<MethodBase> GetAllPatchedMethods()
		{
			lock (locker)
			{
				return HarmonySharedState.GetPatchedMethods();
			}
		}

		/// <summary>Applies all registered patches</summary>
		/// <returns>The generated replacement method</returns>
		///
		public MethodInfo Patch()
		{
			if (original is null)
				throw new NullReferenceException($"Null method for {instance.Id}");

			if (original.IsDeclaredMember() is false)
			{
				var declaredMember = original.GetDeclaredMember();
				throw new ArgumentException($"You can only patch implemented methods/constructors. Patch the declared method {declaredMember.FullDescription()} instead.");
			}

			lock (locker)
			{
				var patchInfo = HarmonySharedState.GetPatchInfo(original) ?? new PatchInfo();

				patchInfo.AddPrefixes(instance.Id, prefix);
				patchInfo.AddPostfixes(instance.Id, postfix);
				patchInfo.AddTranspilers(instance.Id, transpiler);
				patchInfo.AddFinalizers(instance.Id, finalizer);
				patchInfo.AddInnerPrefixes(instance.Id, innerprefix);
				patchInfo.AddInnerPostfixes(instance.Id, innerpostfix);

View on GitHub (pinned to e7872dc170)