skylot/jadx · error · JadxRuntimeException
Failed to replace insn
Error message
Failed to replace insn
What it means
Thrown during SimplifyVisitor's block simplification pass when a simplified instruction cannot be found in the block's instruction list to be replaced. The visitor calls simplifyInsn, which may recursively simplify and modify the list. By the time it tries to replace the original instruction, the list may have changed. If the original instruction is no longer at the expected index and InsnList.getIndex also fails, the replacement is impossible.
Source
Thrown at jadx-core/src/main/java/jadx/core/dex/visitors/SimplifyVisitor.java:93
if (changed || mth.contains(AFlag.REQUEST_CODE_SHRINK)) {
CodeShrinkVisitor.shrinkMethod(mth);
}
}
private boolean simplifyBlock(MethodNode mth, BlockNode block) {
boolean changed = false;
List<InsnNode> list = block.getInstructions();
for (int i = 0; i < list.size(); i++) {
InsnNode insn = list.get(i);
int insnCount = list.size();
InsnNode modInsn = simplifyInsn(mth, insn, null);
if (modInsn != null) {
if (i < list.size() && list.get(i) == insn) {
list.set(i, modInsn);
} else {
int idx = InsnList.getIndex(list, insn);
if (idx == -1) {
throw new JadxRuntimeException("Failed to replace insn");
}
list.set(idx, modInsn);
}
InsnRemover.unbindInsn(mth, insn);
modInsn.rebindArgs();
if (list.size() < insnCount) {
// some insns removed => restart block processing
simplifyBlock(mth, block);
return true;
}
changed = true;
}
}
return changed;
}
private void simplifyArgs(MethodNode mth, InsnNode insn) {
boolean changed = false;View on GitHub (pinned to e738a26571)
Solutions
- Update jadx — the simplify pass is frequently patched for cascade edge cases
- Report the failing method/class as a jadx issue with the input APK
- Try disabling specific simplification passes via command-line flags if available
- As a workaround, use --no-replace-consts to reduce simplification aggressiveness
Defensive patterns
Strategy: try-catch
Try / catch
try {
jadxDecompiler.load();
jadxDecompiler.save();
} catch (JadxRuntimeException e) {
if (e.getMessage().contains("Failed to replace insn")) {
LOG.warn("Simplification cascade issue, retrying with --no-replace-consts");
args.setReplaceConsts(false);
jadxDecompiler = new JadxDecompiler(args);
jadxDecompiler.load();
jadxDecompiler.save();
} else {
throw e;
}
} Prevention
- Keep jadx updated — the SimplifyVisitor cascade handling is frequently patched
- Try --no-replace-consts to reduce simplification aggressiveness
- Report the failing method/APK as a jadx issue with the full stack trace
- Use per-class decompilation to isolate the trigger
When it happens
Trigger: A recursive simplifyInsn call removes or replaces the original instruction (or instructions around it) from the list before the outer replace call executes. The list.size() check and index-based lookup both miss, confirming the instruction was consumed by a nested simplification.
Common situations: Complex instruction chains where one simplification cascades into others (e.g., a series of move/const/arithmetic instructions that collapse together); deeply nested ternary or string concatenation patterns that trigger aggressive simplification.
Related errors
- Payload for fill-array not found at {}
- Payload for switch not found at {}
- Failed to generate code for class: ${cls.getFullName()}
- Failed to process class: ${cls.getFullName()}
- Failed to process method to visitor:
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/7797cbdb94c91a1e.
Report an issue: GitHub.