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

  1. Update jadx — this invariant is checked precisely because earlier passes occasionally miss cases
  2. Report the APK as a jadx issue with the method that triggers it
  3. This error indicates a bug in an earlier visitor pass; the fix is upstream
  4. 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

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


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