pardeike/Harmony · error · ArgumentNullException
Value cannot be null. (Parameter 'method')
Error message
Value cannot be null. (Parameter 'method')
What it means
Harmony's MethodCopier.GetInstructions guards that both the ILGenerator and the MethodBase being copied are non-null before reading the method body. A null 'method' means Harmony was asked to disassemble/instrument a method reference that resolved to null (or was never passed in), typically by a caller of GetInstructions or the public PatchInfo/Transpiler APIs that feed it. The library fails fast here instead of throwing a confusing NullReferenceException deeper in the IL reader.
Solutions
- Fix the reflection lookup so the MethodBase is actually found (correct name, BindingFlags including Static/Instance/NonPublic/Public)
- Check for null before calling any Harmony API and fail with a clear message naming the target you intended to patch
- If the target may be absent in some game versions, guard the patch application behind a version check and skip gracefully
- Verify you are not passing the output of GetPatchInfo or another optional result where a MethodBase is required
Example fix
// before
var m = typeof(Game).GetMethod("Update");
harmony.Patch(m, prefix: new HarmonyMethod(typeof(P), nameof(P.Pre)));
// after
var m = typeof(Game).GetMethod("Update", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic)
?? throw new MissingMethodException(typeof(Game).FullName, "Update");
harmony.Patch(m, prefix: new HarmonyMethod(typeof(P), nameof(P.Pre))); Defensive patterns
Strategy: validation
Validate before calling
var target = AccessTools.Method(typeof(Game), "Update") ?? throw new MissingMethodException(typeof(Game).FullName, "Update"); // then pass 'target' to harmony.Patch / PatchProcessor
Type guard
static MethodInfo RequireMethod(Type t, string name) =>
t.GetMethod(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
?? throw new InvalidOperationException($"{t.FullName}.{name} not found"); Prevention
- Never pass raw GetMethod results to Harmony without a null check
- Use AccessTools.Method which makes intent explicit, and still assert non-null
- Wrap patch bootstrap in a startup method that logs each target before patching
- Add unit tests that resolve every patch target at startup
When it happens
Trigger: Calling Harmony.GetPatchInfo, PatchProcessor, or GetOriginalInstructions-style APIs with a null MethodInfo; a reflection lookup (Type.GetMethod) returned null and the result was passed on without checking; a patch target was removed/renamed so a stored reference is now null.
Common situations: Mods (RimWorld, BepInEx, MelonLoader) patching targets found by string name where a game update renamed the method; passing typeof(X).GetMethod("name") straight into PatchClassProcessor/PatchProcessor without null checks; wrong BindingFlags so the lookup misses the method.
Related errors
- Value cannot be null. (Parameter 'fromMethod')
- Value cannot be null. (Parameter 'config.original')
- The type must declare an empty constructor (the constructor…
- Value cannot be null. (Parameter 'config.methodbase')
- Value cannot be null. (Parameter 'generator')
AI-assisted analysis of pardeike/Harmony@e7872dc170 (2026-09-15).
Data as JSON: /api/errors/87c9efb82ceb198d.
Report an issue: GitHub.
Appendix: source
Thrown at Harmony/Internal/MethodCopier.cs:46
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)
=> reader.FinalizeILCodes(transpilers, stripLastReturn, out hasReturnCode, out methodEndsInDeadCode, endLabels);
internal static List<CodeInstruction> GetInstructions(ILGenerator generator, MethodBase method, int maxTranspilers)
{
if (generator is null)
throw new ArgumentNullException(nameof(generator));
if (method is null)
throw new ArgumentNullException(nameof(method));
var originalVariables = MethodPatcherTools.DeclareOriginalLocalVariables(generator, method);
var copier = new MethodCopier(method, generator, originalVariables);
var info = Harmony.GetPatchInfo(method);
if (info is not null)
{
var sortedTranspilers = PatchFunctions.GetSortedPatchMethods(method, [.. info.Transpilers], false);
for (var i = 0; i < maxTranspilers && i < sortedTranspilers.Count; i++)
copier.AddTranspiler(sortedTranspilers[i]);
}
return copier.Finalize(false, out _, out _, null);
}
}
internal class MethodBodyReader
{
View on GitHub (pinned to e7872dc170)