pardeike/Harmony · error · ArgumentNullException
Value cannot be null. (Parameter 'generator')
Error message
Value cannot be null. (Parameter 'generator')
What it means
MethodCopier.GetInstructions copies a method's instructions into a caller-supplied ILGenerator so transpilers can run on them. The generator is essential (original locals are declared on it), so a null generator is rejected with ArgumentNullException('generator').
Solutions
- Create a valid ILGenerator (e.g. from a DynamicMethod or MethodBuilder) and pass it to GetInstructions
- Trace where your generator value comes from and ensure it is initialized before the call
- If using Harmony's high-level Patch API instead, the generator is created for you — prefer harmony.Patch over raw internals
- Add a guard that fails early with your own message when the generator could not be created
Example fix
// before
var instructions = MethodCopier.GetInstructions(null, originalMethod, 3);
// after
var dm = new DynamicMethod("Copy", originalMethod.ReturnType, originalMethod.GetParameters().Select(p => p.ParameterType).ToArray());
var instructions = MethodCopier.GetInstructions(dm.GetILGenerator(), originalMethod, 3); Defensive patterns
Strategy: validation
Validate before calling
if (generator is null) throw new InvalidOperationException("ILGenerator must be created before calling MethodCopier.GetInstructions"); Try / catch
try { var instrs = MethodCopier.GetInstructions(generator, method, maxTranspilers); }
catch (ArgumentNullException ex) when (ex.ParamName == "generator") { /* create DynamicMethod/ILGenerator and retry */ } Prevention
- Create the ILGenerator from a DynamicMethod before touching Harmony internals
- Prefer the high-level harmony.Patch API which manages generators itself
- Null-check lazily created generators before use
When it happens
Trigger: Calling MethodCopier.GetInstructions(null, method, maxTranspilers) or a patch pipeline that resolved its ILGenerator lazily and got null (e.g. MethodPatcher building a replacement body without a valid generator).
Common situations: Custom patch tooling built on Harmony internals passing a generator created conditionally; refactors where the generator creation step was skipped; using GetInstructions outside Harmony's normal patch flow without creating a DynamicMethod/ILGenerator first.
Related errors
- Unexpected null argument
- Unbalanced exception markers – cannot rewrite.
- Value cannot be null. (Parameter 'fromMethod')
- Value cannot be null. (Parameter 'config.methodbase')
- Value cannot be null. (Parameter 'method')
AI-assisted analysis of pardeike/Harmony@e7872dc170 (2026-09-15).
Data as JSON: /api/errors/73d1c5d6c2234c9a.
Report an issue: GitHub.
Appendix: source
Thrown at Harmony/Internal/MethodCopier.cs:44
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)
=> 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);
}
}
View on GitHub (pinned to e7872dc170)