skylot/jadx · error · JadxRuntimeException
Found unreachable blocks
Error message
Found unreachable blocks
What it means
Thrown during dominator tree construction. The algorithm requires all basic blocks to be reachable from the entry block via DFS traversal. If the DFS-visited set is smaller than the total block count, unreachable blocks remain, and the dominator algorithm (which assumes full reachability) cannot proceed safely.
Source
Thrown at jadx-core/src/main/java/jadx/core/dex/visitors/blocks/DominatorTree.java:34
* Cooper, Keith D.; Harvey, Timothy J; Kennedy, Ken (2001).
* "A Simple, Fast Dominance Algorithm"
* http://www.hipersoft.rice.edu/grads/publications/dom14.pdf
*/
@SuppressWarnings("JavadocLinkAsPlainText")
public class DominatorTree {
public static void compute(MethodNode mth) {
List<BlockNode> sorted = sortBlocks(mth);
BlockNode[] doms = build(sorted, BlockNode::getPredecessors);
apply(sorted, doms);
}
private static List<BlockNode> sortBlocks(MethodNode mth) {
int blocksCount = mth.getBasicBlocks().size();
List<BlockNode> sorted = new ArrayList<>(blocksCount);
BlockUtils.visitDFS(mth, sorted::add);
if (sorted.size() != blocksCount) {
throw new JadxRuntimeException("Found unreachable blocks");
}
mth.setBasicBlocks(sorted);
return sorted;
}
static BlockNode[] build(List<BlockNode> sorted, Function<BlockNode, List<BlockNode>> predFunc) {
int blocksCount = sorted.size();
BlockNode[] doms = new BlockNode[blocksCount];
doms[0] = sorted.get(0);
boolean changed = true;
while (changed) {
changed = false;
for (int blockId = 1; blockId < blocksCount; blockId++) {
BlockNode b = sorted.get(blockId);
List<BlockNode> preds = predFunc.apply(b);
int pickedPred = -1;
BlockNode newIDom = null;
for (BlockNode pred : preds) {View on GitHub (pinned to e738a26571)
Solutions
- Update jadx — this invariant is checked precisely because earlier passes occasionally miss cases
- Report the APK as a jadx issue with the method that triggers it
- This error indicates a bug in an earlier visitor pass; the fix is upstream
- Try decompiling individual classes to isolate the trigger
Defensive patterns
Strategy: try-catch
Try / catch
try {
jadxDecompiler.load();
jadxDecompiler.save();
} catch (JadxRuntimeException e) {
if (e.getMessage().contains("Found unreachable blocks")) {
LOG.warn("Dominator tree found unreachable blocks, this is a bug in earlier passes");
for (ClassNode cls : jadxDecompiler.getClasses()) {
try {
jadxDecompiler.decompileClass(cls);
} catch (JadxRuntimeException ex) {
LOG.warn("Skipped: {}", cls.getFullName());
}
}
} else {
throw e;
}
} Prevention
- Keep jadx updated — this invariant fires when earlier passes miss unreachable blocks
- Report the APK as a jadx issue — this indicates a bug in block processing
- Decompile classes individually to isolate which method triggers it
- This is not fixable from user input; it requires a jadx code fix
When it happens
Trigger: BlockUtils.visitDFS visits fewer blocks than mth.getBasicBlocks().size(). This is a post-block-processing invariant check — dead blocks should have been removed before dominator computation.
Common situations: A block-processing pass created or left orphaned blocks without removing them; the block cleanup pass (BlockProcessor) didn't run or didn't catch all unreachable blocks; obfuscated control flow that creates unreachable islands the cleanup doesn't recognize.
Related errors
- No immediate dominator for block: {}
- Failed to find top block for try-catch from: {}
- Unreachable block: {}
- Copy blocks tree failed. Missing block for connection: {}
- Unexpected missing predecessor for block: {}
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/6458583c969a4a87.
Report an issue: GitHub.