pardeike/Harmony · error · Exception

Cannot find instruction for

Error message

Cannot find instruction for {offset:X4}

What it means

After the offset bounds checks pass, GetInstruction binary-searches the copied instruction list for the instruction starting at that offset. Reaching the end of the search means no instruction begins at the requested offset — i.e. an operand referenced a mid-instruction or nonexistent offset. Harmony wraps this in a plain Exception naming the offset in hex.

Solutions

  1. Rewrite transpilers to manipulate instructions via labels and CodeInstruction objects, never by setting raw integer offsets into operands
  2. Test the same patch against an unobfuscated build to confirm obfuscation is the cause
  3. Bisect which transpiler/method combination triggers it and file a Harmony issue with the IL if it looks like a reader bug
  4. Update Harmony to the latest version — IL decoding bugs are periodically fixed

Example fix

// before
ci.operand = 0x0012; // raw offset, no matching instruction
// after
var target = instructions.First(i => i.offset == 0x0012 || i.labels.Any());
var lbl = generator.DefineLabel();
target.labels.Add(lbl);
ci.operand = lbl;
Defensive patterns

Strategy: try-catch

Validate before calling

// smoke-test the full patch pipeline at startup for every transpiled target
foreach (var t in targets) { try { new PatchProcessor(t).AddTranspiler(tr).Patch(); } catch (Exception e) { Log.Error($"{t}: {e.Message}"); } }

Try / catch

try { harmony.Patch(target, transpiler: trans); }
catch (Exception ex) when (ex.Message.StartsWith("Cannot find instruction for"))
{ Log.Error($"IL mapping failed for {target}: {ex.Message}"); }

Prevention

When it happens

Trigger: IL operands pointing into the middle of an instruction (mis-decoded stream); transpilers that changed instruction sizes/positions leaving dangling branch operands; IL from obfuscated assemblies that the linear reader cannot map correctly.

Common situations: Transpiling obfuscated game code; custom transpilers that mutate operand values to raw offsets instead of labels; edge-case IL patterns on older Mono/JIT implementations.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at Harmony/Internal/MethodCopier.cs:640

				if (isEndOfInstruction)
				{
					if (offset == instruction.offset + instruction.GetSize() - 1)
						return instruction;
				}
				else
				{
					if (offset == instruction.offset)
						return instruction;
				}

				if (offset < instruction.offset)
					max = mid - 1;
				else
					min = mid + 1;
			}

			throw new Exception($"Cannot find instruction for {offset:X4}");
		}

		static bool TargetsLocalVariable(OpCode opcode) => opcode.Name.Contains("loc");

		LocalVariableInfo GetLocalVariable(int index) => localVariables?[index];

		ParameterInfo GetParameter(int index)
		{
			if (index == 0)
				return this_parameter;

			return parameters[index - 1];
		}

		OpCode ReadOpCode()
		{
			var op = ilBytes.ReadByte();
			return op != 0xfe

View on GitHub (pinned to e7872dc170)