pardeike/Harmony · error · ArgumentException

Can not get IL bytes of method

Error message

Can not get IL bytes of method {method.FullDescription()}

What it means

MethodBodyReader asks the runtime for the method's IL as a byte array (MethodBase.GetMethodBody().GetILAsByteArray()) and throws if the bytes are null. This happens for methods that have no IL body at all — abstract methods, extern/P-Invoke methods, runtime-intrinsic methods, or methods implemented natively. Harmony cannot copy or transpile a method that has no IL.

Solutions

  1. Patch the concrete implementation (derived type's override) instead of the abstract/interface method
  2. Do not attempt to patch extern/P-Invoke/native methods; patch a managed caller instead or use a different hooking technique
  3. Check method.IsAbstract / method.GetMethodBody() == null before patching and skip or warn
  4. For interface contracts, patch all concrete implementations or use a proxy/dispatcher pattern

Example fix

// before
var m = typeof(IFoo).GetMethod("Bar"); // abstract - no IL
harmony.Patch(m, transpiler: trans);
// after
var m = typeof(FooImpl).GetMethod("Bar"); // concrete override with IL body
if (m.GetMethodBody() != null)
    harmony.Patch(m, transpiler: trans);
Defensive patterns

Strategy: validation

Validate before calling

bool CanPatch(MethodBase m) => m is not null && !m.IsAbstract && !m.IsVirtual || (m.IsVirtual && m.GetMethodBody() is not null);
// safer: check body directly
bool HasIl(MethodBase m) => m?.GetMethodBody()?.GetILAsByteArray() is { Length: > 0 };

Type guard

static bool IsPatchable(MethodBase m) =>
    m is MethodInfo mi && mi.GetMethodBody() != null;

Try / catch

try { harmony.Patch(target, transpiler: trans); }
catch (ArgumentException ex) when (ex.Message.Contains("Can not get IL bytes"))
{ Log.Warn($"{target.FullDescription()} has no IL body (abstract/extern/native) — skipping"); }

Prevention

When it happens

Trigger: Attempting to Patch() or reverse-patch an abstract or interface method; patching an extern or P/Invoke (DllImport) method; patching methods with MethodImplAttributes like AggressiveInlining + native/runtime on some runtimes; patching into a Mono/runtime where GetMethodBody returns null for the target.

Common situations: Trying to transpile interface or abstract methods instead of the concrete implementation; patching native methods (UnityEngine internal calls) which have no CIL body; targeting a property accessor that is abstract; AOT/IL2CPP environments where JIT IL bodies are unavailable.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at Harmony/Internal/MethodCopier.cs:107

		}

		internal MethodBodyReader(MethodBase method, ILGenerator generator)
		{
			this.generator = generator;
			this.method = method;
			module = method.Module;

			var body = method.GetMethodBody();
			if ((body?.GetILAsByteArray()?.Length ?? 0) == 0)
			{
				ilBytes = new ByteBuffer([]);
				ilInstructions = [];
			}
			else
			{
				var bytes = body.GetILAsByteArray();
				if (bytes is null)
					throw new ArgumentException("Can not get IL bytes of method " + method.FullDescription());
				ilBytes = new ByteBuffer(bytes);
				ilInstructions = new List<ILInstruction>((bytes.Length + 1) / 2);
			}

			var type = method.DeclaringType;

			if (type is not null && type.IsGenericType)
			{
				try
				{ typeArguments = type.GetGenericArguments(); }
				catch { typeArguments = null; }
			}

			if (method.IsGenericMethod)
			{
				try
				{ methodArguments = method.GetGenericArguments(); }
				catch { methodArguments = null; }

View on GitHub (pinned to e7872dc170)