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
- Update jadx; CFG/branch-shape assumptions are tuned over releases.
- Report the method/class with the offending node and list from the message.
- 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.
- 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
- Prefer BlockUtils.selectOtherSafe (returns null) when you can tolerate a non-binary branch.
- If you call selectOther directly, ensure the list is a binary branch first.
- Update jadx; CFG shape assumptions are tuned over releases.
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
- Can't find block by offset: {} in list {}
- Insn not found in method: {}
- Failed to find top block for try-catch from: {}
- Unreachable block: {}
- Copy blocks tree failed. Missing block for connection: {}
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/66fd48082eeb9a7e.
Report an issue: GitHub.