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
- Upgrade JADX — PHI construction bugs are regularly fixed.
- Try disabling specific passes if exposed via CLI/API (e.g. fallback decompilation mode).
- Decompile the class in isolation (-j 1) and report the method to the JADX tracker.
- 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
- Report PHI duplicate-predecessor bugs upstream — they are usually internal regressions.
- Decompile the class in isolation to get a minimal reproducer.
- Keep JADX updated.
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
- Several immutable types in one variable: {}, vars: {}
- Regions count limit reached at block {}
- Phi nodes fix limit reached!
- Type update failed for variable: {}, new type: {}
- Unsigned byte value is too big:
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/093d3449d62c0061.
Report an issue: GitHub.