{"record":{"id":"093d3449d62c0061","repo":"skylot/jadx","slug":"duplicate-predecessors-in-phi-insn","errorCode":null,"errorMessage":"Duplicate predecessors in PHI insn: {}, {}","messagePattern":"Duplicate predecessors in PHI insn: (.+?), (.+?)","errorType":"exception","errorClass":"JadxRuntimeException","httpStatus":null,"severity":"error","filePath":"jadx-core/src/main/java/jadx/core/dex/instructions/PhiInsn.java","lineNumber":45,"sourceCode":"\t\tsetResult(InsnArg.reg(regNum, ArgType.UNKNOWN));\n\t\tadd(AFlag.DONT_INLINE);\n\t\tadd(AFlag.DONT_GENERATE);\n\t}\n\n\tprivate PhiInsn(int argsCount) {\n\t\tsuper(InsnType.PHI, argsCount);\n\t\tthis.blockBinds = new ArrayList<>(argsCount);\n\t}\n\n\tpublic RegisterArg bindArg(BlockNode pred) {\n\t\tRegisterArg arg = InsnArg.reg(getResult().getRegNum(), getResult().getInitType());\n\t\tbindArg(arg, pred);\n\t\treturn arg;\n\t}\n\n\tpublic void bindArg(RegisterArg arg, BlockNode pred) {\n\t\tif (blockBinds.contains(pred)) {\n\t\t\tthrow new JadxRuntimeException(\"Duplicate predecessors in PHI insn: \" + pred + \", \" + this);\n\t\t}\n\t\tif (pred == null) {\n\t\t\tthrow new JadxRuntimeException(\"Null bind block in PHI insn: \" + this);\n\t\t}\n\t\tsuper.addArg(arg);\n\t\tblockBinds.add(pred);\n\t}\n\n\t@Nullable\n\tpublic BlockNode getBlockByArg(RegisterArg arg) {\n\t\tint index = getArgIndex(arg);\n\t\tif (index == -1) {\n\t\t\treturn null;\n\t\t}\n\t\treturn blockBinds.get(index);\n\t}\n\n\tpublic BlockNode getBlockByArgIndex(int argIndex) {","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-core/src/main/java/jadx/core/dex/instructions/PhiInsn.java#L27-L63","documentation":"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.","triggerScenarios":"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.","commonSituations":"Obfuscated bytecode with dense/irregular jump graphs, code that triggers edge-case PHI merging, or a regression in JADX's block/SSA passes.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    jadx.load();\n} catch (JadxRuntimeException e) {\n    if (e.getMessage().contains(\"Duplicate predecessors in PHI\")) {\n        log.warn(\"PHI construction internal error; report to JADX tracker\", e);\n    } else throw e;\n}","preventionTips":["Report PHI duplicate-predecessor bugs upstream — they are usually internal regressions.","Decompile the class in isolation to get a minimal reproducer.","Keep JADX updated."],"tags":["phi","ssa","control-flow","internal-bug","obfuscation"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}