pardeike/Harmony · error · ArgumentNullException

Value cannot be null. (Parameter 'fromMethod')

Error message

Value cannot be null. (Parameter 'fromMethod')

What it means

MethodCopier copies the IL body of one method into an ILGenerator. The primary constructor requires the source MethodBase; passing null is caught immediately with ArgumentNullException('fromMethod') before any body reading begins.

Solutions

  1. Verify the source method reference is non-null before constructing the copier (check the result of AccessTools.Method/Type.GetMethod)
  2. Fix the method lookup — name, BindingFlags, and parameter types must match the real method
  3. Confirm the target method exists in the assembly and is not trimmed away
  4. If null is legitimately possible, fall back to emitting new IL instead of copying

Example fix

// before
var copier = new MethodCopier(AccessTools.Method(typeof(Foo), "Baar"), il); // Baar typo → null
// after
var src = AccessTools.Method(typeof(Foo), "Bar") ?? throw new InvalidOperationException("Bar not found");
var copier = new MethodCopier(src, il);
Defensive patterns

Strategy: validation

Validate before calling

var src = AccessTools.Method(typeof(Target), "MethodName");
if (src is null) throw new InvalidOperationException("Source method not found — fix name/signature before copying IL");

Type guard

static MethodInfo? FindMethod(Type t, string name) => t.GetMethod(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);

Try / catch

try { var copier = new MethodCopier(src, il); }
catch (ArgumentNullException ex) when (ex.ParamName == "fromMethod") { /* method lookup failed — resolve before retry */ }

Prevention

When it happens

Trigger: Calling MethodCopier(null, ilGenerator) or internal copy paths (e.g. patch/mini-copy helpers) where the resolved source method (from PatchFunctions/GetOriginalMethod chains) came back null — commonly when an original method lookup by name/type failed upstream and the null flowed into the copier.

Common situations: AccessTools.Method returned null because of a typo'd name or signature mismatch, then the result was passed on to Harmony's copy machinery; patching a method that was stripped by trimming/IL2CPP; building dynamic replacement methods with a null source.

Related errors


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

Appendix: source

Thrown at Harmony/Internal/MethodCopier.cs:20

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace HarmonyLib
{
	internal class MethodCopier
	{
		readonly MethodBodyReader reader;
		readonly List<MethodInfo> transpilers = [];

		internal MethodCopier(MethodBase fromMethod, ILGenerator toILGenerator, LocalBuilder[] existingVariables = null)
		{
			if (fromMethod is null)
				throw new ArgumentNullException(nameof(fromMethod));
			reader = new MethodBodyReader(fromMethod, toILGenerator);
			reader.DeclareVariables(existingVariables);
			reader.GenerateInstructions();
		}

		internal MethodCopier(MethodCreatorConfig config)
		{
			if (config.MethodBase is null)
				throw new ArgumentNullException("config.methodbase");
			reader = new MethodBodyReader(config.MethodBase, config.il);
			reader.DeclareVariables(config.originalVariables);
			reader.GenerateInstructions();
			reader.SetDebugging(config.debug);
		}

		internal void AddTranspiler(MethodInfo transpiler) => transpilers.Add(transpiler);

		internal List<CodeInstruction> Finalize(bool stripLastReturn, out bool hasReturnCode, out bool methodEndsInDeadCode, List<Label> endLabels)

View on GitHub (pinned to e7872dc170)