{"record":{"id":"802bbbeb7bfb8bcb","repo":"pardeike/Harmony","slug":"instruction-offset-offset-is-outside-valid-range-0","errorCode":null,"errorMessage":"Instruction offset {offset} is outside valid range 0 - {instruction.offset + instruction.GetSize() - 1}","messagePattern":"Instruction offset (.+?) is outside valid range 0 - (.+?)","errorType":"exception","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"Harmony/Internal/MethodCopier.cs","lineNumber":614,"sourceCode":"\t\t\t\t\t\tinstruction.argument = idx;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tthrow new NotSupportedException();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tILInstruction GetInstruction(int offset, bool isEndOfInstruction)\r\n\t\t{\r\n\t\t\tif (offset < 0)\r\n\t\t\t\tthrow new ArgumentOutOfRangeException(nameof(offset), offset, $\"Instruction offset {offset} is less than 0\");\r\n\r\n\t\t\tvar lastInstructionIndex = ilInstructions.Count - 1;\r\n\t\t\tvar instruction = ilInstructions[lastInstructionIndex];\r\n\t\t\tif (offset > instruction.offset + instruction.GetSize() - 1)\r\n\t\t\t\tthrow new ArgumentOutOfRangeException(nameof(offset), offset, $\"Instruction offset {offset} is outside valid range 0 - {instruction.offset + instruction.GetSize() - 1}\");\r\n\r\n\t\t\tvar min = 0;\r\n\t\t\tvar max = lastInstructionIndex;\r\n\t\t\twhile (min <= max)\r\n\t\t\t{\r\n\t\t\t\tvar mid = min + ((max - min) / 2);\r\n\t\t\t\tinstruction = ilInstructions[mid];\r\n\r\n\t\t\t\tif (isEndOfInstruction)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (offset == instruction.offset + instruction.GetSize() - 1)\r\n\t\t\t\t\t\treturn instruction;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tif (offset == instruction.offset)\r\n\t\t\t\t\t\treturn instruction;\r\n\t\t\t\t}\r","sourceCodeStart":596,"sourceCodeEnd":632,"githubUrl":"https://github.com/pardeike/Harmony/blob/e7872dc17008bc0ca2b3de1f53fd4120dbd7a17c/Harmony/Internal/MethodCopier.cs#L596-L632","documentation":"GetInstruction also bounds-checks the requested offset against the last instruction's end (instruction.offset + GetSize() - 1). An offset beyond the emitted IL range means operand resolution pointed past the method body — again a symptom of IL decoding trouble or a transpiler producing inconsistent instruction streams. Harmony throws ArgumentOutOfRangeException showing the valid range.","triggerScenarios":"Branch/switch operands in the copied method resolving beyond the end of the IL byte array; transpilers that replaced instructions while leaving stale operand references; decoding IL from obfuscated or hand-tweaked assemblies.","commonSituations":"Transpiling modded/obfuscated assemblies; methods where a custom transpiler removed instructions that other instructions still branch to; Mono runtime IL quirks with switch opcodes.","solutions":["Ensure transpilers never remove or relocate instructions that are branch targets without fixing labels/operands","Deobfuscate the target assembly or choose a safer patch target (a caller/callee with clean IL)","Bisect transpilers to find the one corrupting the instruction list, and use label-based operands instead of raw offsets","If plain vanilla IL triggers it, file a Harmony bug with the failing method's description"],"exampleFix":"// before\nlist.RemoveAll(ci => ci.opcode == OpCodes.Nop); // removes branch targets\n// after\n// keep instructions carrying labels, or retarget their labels first\nforeach (var ci in instructions.Where(ci => ci.opcode == OpCodes.Nop && ci.labels.Count == 0 && ci.opcode != OpCodes.Nop || (ci.opcode == OpCodes.Nop && ci.labels.Count == 0)))\n    list.Remove(ci); // only strip label-free nops","handlingStrategy":"try-catch","validationCode":"// validate your transpiler in isolation on the target method at startup:\nvar copy = PatchProcessor.ReadMethodBody(target); // or run the patch in a try/catch during boot","typeGuard":null,"tryCatchPattern":"try { harmony.Patch(target, transpiler: trans); }\ncatch (ArgumentOutOfRangeException ex) when (ex.Message.Contains(\"outside valid range\"))\n{ Log.Error($\"Branch target beyond IL end while transpiling {target}: {ex.Message}\"); }","preventionTips":["Bisect transpilers when a target fails to find the offending one","Preserve instruction labels when removing/replacing instructions","Avoid transpiling obfuscated methods; patch an alternative target instead","Pin to a recent Harmony version"],"tags":["harmony","il","argument-out-of-range"],"backgroundTag":"argument-out-of-range","analyzedSha":"e7872dc17008bc0ca2b3de1f53fd4120dbd7a17c","analyzedAt":"2026-09-15T22:47:11.550Z","contentChangedAt":"2026-09-15T22:47:11.550Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}