skylot/jadx · error · JadxRuntimeException

Duplicate predecessors in PHI insn: {}, {}

Error message

Duplicate predecessors in PHI insn: {}, {}

What it means

In PhiInsn.bindArg(RegisterArg, BlockNode), the same BlockNode predecessor is being bound twice to a PHI instruction. PHI nodes map one argument per predecessor block; a duplicate indicates the SSA/PHI construction logic produced redundant predecessor edges — an internal invariant violation rather than an input-format error.

Source

Thrown at jadx-core/src/main/java/jadx/core/dex/instructions/PhiInsn.java:45

		setResult(InsnArg.reg(regNum, ArgType.UNKNOWN));
		add(AFlag.DONT_INLINE);
		add(AFlag.DONT_GENERATE);
	}

	private PhiInsn(int argsCount) {
		super(InsnType.PHI, argsCount);
		this.blockBinds = new ArrayList<>(argsCount);
	}

	public RegisterArg bindArg(BlockNode pred) {
		RegisterArg arg = InsnArg.reg(getResult().getRegNum(), getResult().getInitType());
		bindArg(arg, pred);
		return arg;
	}

	public void bindArg(RegisterArg arg, BlockNode pred) {
		if (blockBinds.contains(pred)) {
			throw new JadxRuntimeException("Duplicate predecessors in PHI insn: " + pred + ", " + this);
		}
		if (pred == null) {
			throw new JadxRuntimeException("Null bind block in PHI insn: " + this);
		}
		super.addArg(arg);
		blockBinds.add(pred);
	}

	@Nullable
	public BlockNode getBlockByArg(RegisterArg arg) {
		int index = getArgIndex(arg);
		if (index == -1) {
			return null;
		}
		return blockBinds.get(index);
	}

	public BlockNode getBlockByArgIndex(int argIndex) {

View on GitHub (pinned to e738a26571)

Solutions

  1. Upgrade JADX — PHI construction bugs are regularly fixed.
  2. Try disabling specific passes if exposed via CLI/API (e.g. fallback decompilation mode).
  3. Decompile the class in isolation (-j 1) and report the method to the JADX tracker.
  4. Use --show-bad-code to obtain partial output for surrounding methods.
Defensive patterns

Strategy: try-catch

Try / catch

try {
    jadx.load();
} catch (JadxRuntimeException e) {
    if (e.getMessage().contains("Duplicate predecessors in PHI")) {
        log.warn("PHI construction internal error; report to JADX tracker", e);
    } else throw e;
}

Prevention

When it happens

Trigger: During SSA analysis, a block is added as a PHI predecessor that is already in blockBinds. This usually stems from unusual control-flow graphs (e.g. a block that is a predecessor via multiple edges) or a bug in PHI construction under obfuscation.

Common situations: Obfuscated bytecode with dense/irregular jump graphs, code that triggers edge-case PHI merging, or a regression in JADX's block/SSA passes.

Related errors


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