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

  1. Update jadx — the simplify pass is frequently patched for cascade edge cases
  2. Report the failing method/class as a jadx issue with the input APK
  3. Try disabling specific simplification passes via command-line flags if available
  4. 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

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


AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14). Data as JSON: /api/errors/7797cbdb94c91a1e. Report an issue: GitHub.