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
- Rewrite transpilers to manipulate instructions via labels and CodeInstruction objects, never by setting raw integer offsets into operands
- Test the same patch against an unobfuscated build to confirm obfuscation is the cause
- Bisect which transpiler/method combination triggers it and file a Harmony issue with the IL if it looks like a reader bug
- 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
- Use CodeInstruction labels for all branch manipulation; never assign raw offsets to operand
- Do not mutate the operands of copied instructions that reference fixed offsets
- Verify patches on an unobfuscated build to isolate obfuscation-induced IL weirdness
- Report reproducible vanilla-IL failures to the Harmony issue tracker
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
- The type must declare an empty constructor (the constructor…
- Can not get IL bytes of method
- Instruction offset is less than 0
- Instruction offset is outside valid range 0
- Unexpected null argument
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)