pardeike/Harmony · error · ArgumentException
Unexpected null argument
Error message
Unexpected null argument
What it means
Transpilers.MethodReplacer validates its from argument before scanning instructions. If from (the method to be replaced in the IL) is null, it throws an ArgumentException with param name 'from' and message 'Unexpected null argument'.
Solutions
- Fix the lookup for 'from' so it resolves the target method
- Null-check both MethodBase values before calling MethodReplacer and throw/log a descriptive error
- Verify the replaced method exists in the current target assembly version
Example fix
// before
instructions.MethodReplacer(AccessTools.Method(typeof(UnityEngine.Time), "get_time"), AccessTools.Method(typeof(FakeTime), "get_time"));
// after
var from = AccessTools.Method(typeof(UnityEngine.Time), "get_time") ?? throw new Exception("Time.get_time not found");
var to = AccessTools.Method(typeof(FakeTime), "get_time");
instructions.MethodReplacer(from, to); Defensive patterns
Strategy: validation
Validate before calling
var from = AccessTools.Method(fromType, fromName) ?? throw new InvalidOperationException($"Replaced method {fromType}.{fromName} not found"); Try / catch
try { instructions = instructions.MethodReplacer(from, to); }
catch (ArgumentException ex) when (ex.ParamName == "from") { logger.Error("Transpiler 'from' method lookup failed"); throw; } Prevention
- Resolve and null-check both MethodBase values before building the transpiler pipeline
- Use static cached MethodInfo fields initialized once with null checks
- Add a startup self-test that runs the transpiler on an empty instruction list to catch null lookups early
When it happens
Trigger: Passing a null MethodBase as the 'from' parameter — typically the result of a failed AccessTools.Method/Constructor lookup inside a transpiler that calls instructions.MethodReplacer(from, to).
Common situations: Transpiler authors inline AccessTools lookups directly into the MethodReplacer call; a typo or renamed target method in a game update makes the lookup return null at patch time.
Related errors
- Value cannot be null. (Parameter 'generator')
- The type must declare an empty constructor (the constructor…
- Unbalanced exception markers – cannot rewrite.
- Value cannot be null. (Parameter 'fromMethod')
- Value cannot be null. (Parameter 'config.methodbase')
AI-assisted analysis of pardeike/Harmony@e7872dc170 (2026-09-15).
Data as JSON: /api/errors/94e6d25c4eb7922c.
Report an issue: GitHub.
Appendix: source
Thrown at Harmony/Public/Transpilers.cs:22
using System.Reflection;
using System.Reflection.Emit;
namespace HarmonyLib
{
/// <summary>A collection of commonly used transpilers</summary>
///
public static class Transpilers
{
/// <summary>A transpiler that replaces all occurrences of a given method with another one using the same signature</summary>
/// <param name="instructions">The enumeration of <see cref="CodeInstruction"/> to act on</param>
/// <param name="from">Method or constructor to search for</param>
/// <param name="to">Method or constructor to replace with</param>
/// <returns>Modified enumeration of <see cref="CodeInstruction"/></returns>
///
public static IEnumerable<CodeInstruction> MethodReplacer(this IEnumerable<CodeInstruction> instructions, MethodBase from, MethodBase to)
{
if (from is null)
throw new ArgumentException("Unexpected null argument", nameof(from));
if (to is null)
throw new ArgumentException("Unexpected null argument", nameof(to));
foreach (var instruction in instructions)
{
var method = instruction.operand as MethodBase;
if (method == from)
{
instruction.opcode = to.IsConstructor ? OpCodes.Newobj : OpCodes.Call;
instruction.operand = to;
}
yield return instruction;
}
}
/// <summary>A transpiler that alters instructions that match a predicate by calling an action</summary>
/// <param name="instructions">The enumeration of <see cref="CodeInstruction"/> to act on</param>
/// <param name="predicate">A predicate selecting the instructions to change</param>
View on GitHub (pinned to e7872dc170)