skylot/jadx · error · JadxRuntimeException

Incorrect nodes count for selectOther: {} in {}

Error message

Incorrect nodes count for selectOther: {} in {}

What it means

Thrown by BlockUtils.selectOther when, after optionally cleaning a >2 list, the list does not contain exactly two blocks. selectOther is the helper used by IfNode/ResolveJavaJSR/LoopInfo to pick 'the other' branch of a binary split, so it assumes exactly two candidates. Failure indicates the input list was not a binary branch (size 0, 1, 3+, or a list that cleanBlockList could not reduce).

Source

Thrown at jadx-core/src/main/java/jadx/core/utils/BlockUtils.java:68

	public static BlockNode getBlockByOffset(int offset, Iterable<BlockNode> casesBlocks) {
		for (BlockNode block : casesBlocks) {
			if (block.getStartOffset() == offset) {
				return block;
			}
		}
		throw new JadxRuntimeException("Can't find block by offset: "
				+ InsnUtils.formatOffset(offset)
				+ " in list " + casesBlocks);
	}

	public static BlockNode selectOther(BlockNode node, List<BlockNode> blocks) {
		List<BlockNode> list = blocks;
		if (list.size() > 2) {
			list = cleanBlockList(list);
		}
		if (list.size() != 2) {
			throw new JadxRuntimeException("Incorrect nodes count for selectOther: " + node + " in " + list);
		}
		BlockNode first = list.get(0);
		if (first != node) {
			return first;
		} else {
			return list.get(1);
		}
	}

	public static BlockNode selectOtherSafe(BlockNode node, List<BlockNode> blocks) {
		int size = blocks.size();
		if (size == 1) {
			BlockNode first = blocks.get(0);
			return first != node ? first : null;
		}
		if (size == 2) {
			BlockNode first = blocks.get(0);
			return first != node ? first : blocks.get(1);

View on GitHub (pinned to e738a26571)

Solutions

  1. Update jadx; CFG/branch-shape assumptions are tuned over releases.
  2. Report the method/class with the offending node and list from the message.
  3. Use selectOtherSafe (which returns null instead of throwing) if you are calling BlockUtils directly in a plugin/pass and can tolerate a non-binary branch.
  4. Catch JadxRuntimeException per method when embedding jadx.

Example fix

// before - throws on non-binary lists
BlockNode other = BlockUtils.selectOther(node, blocks);
// after - tolerate non-binary shape
BlockNode other = BlockUtils.selectOtherSafe(node, blocks);
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check before calling selectOther
List<BlockNode> l = blocks.size() > 2 ? cleanBlockList(blocks) : blocks;
if (l.size() == 2) {
    BlockNode other = BlockUtils.selectOther(node, l);
}

Try / catch

BlockNode other;
try {
    other = BlockUtils.selectOther(node, blocks);
} catch (JadxRuntimeException e) {
    other = null; // not a binary branch
}

Prevention

When it happens

Trigger: Calling selectOther(node, blocks) on a successors/predecessors list that is not a binary branch - e.g. an if-instruction with one target (degenerate), a block with three successors passed where two were expected, or a list whose entries are filtered away by cleanBlockList.

Common situations: Reachable from IfNode (which expects exactly then/else), LoopInfo (loop end vs. pre-header), and ResolveJavaJSR. Usually a symptom of a malformed CFG built earlier in the pipeline rather than a problem with your input per se.

Related errors


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