skylot/jadx · error · JadxRuntimeException
Copy blocks tree failed. Missing block for connection: {}
Error message
Copy blocks tree failed. Missing block for connection: {} What it means
Thrown when copying a block tree (used for method duplication in JSR resolution and inlining). The copy process builds a map from original blocks to new blocks, then reconnects successors. If a successor block has no entry in the map, the tree structure is incomplete and the copy cannot proceed.
Source
Thrown at jadx-core/src/main/java/jadx/core/dex/visitors/blocks/BlockSplitter.java:235
BlockNode newBlock = startNewBlock(mth, block.getStartOffset());
copyBlockData(block, newBlock);
copyBlocks.add(newBlock);
map.put(block, newBlock);
}
for (BlockNode block : blocks) {
BlockNode newBlock = getNewBlock(block, map);
for (BlockNode successor : block.getSuccessors()) {
BlockNode newSuccessor = getNewBlock(successor, map);
BlockSplitter.connect(newBlock, newSuccessor);
}
}
return copyBlocks;
}
private static BlockNode getNewBlock(BlockNode block, Map<BlockNode, BlockNode> map) {
BlockNode newBlock = map.get(block);
if (newBlock == null) {
throw new JadxRuntimeException("Copy blocks tree failed. Missing block for connection: " + block);
}
return newBlock;
}
static void replaceTarget(BlockNode source, BlockNode oldTarget, BlockNode newTarget) {
InsnNode lastInsn = BlockUtils.getLastInsn(source);
if (lastInsn instanceof TargetInsnNode) {
((TargetInsnNode) lastInsn).replaceTargetBlock(oldTarget, newTarget);
}
}
private static void setupConnectionsFromJumps(MethodNode mth, Map<Integer, BlockNode> blocksMap) {
for (BlockNode block : mth.getBasicBlocks()) {
for (InsnNode insn : block.getInstructions()) {
List<JumpInfo> jumps = insn.getAll(AType.JUMP);
for (JumpInfo jump : jumps) {
BlockNode srcBlock = getBlock(jump.getSrc(), blocksMap);
BlockNode thisBlock = getBlock(jump.getDest(), blocksMap);View on GitHub (pinned to e738a26571)
Solutions
- Update jadx — block tree copy logic is periodically refined
- Report the APK and failing method as a jadx issue with the full stack trace
- Try with --no-inline-anonymous or similar flags that reduce code duplication
- Exclude the problematic class if the rest of the APK decompiles fine
Defensive patterns
Strategy: try-catch
Try / catch
try {
jadxDecompiler.load();
jadxDecompiler.save();
} catch (JadxRuntimeException e) {
if (e.getMessage().contains("Copy blocks tree failed")) {
LOG.warn("Block tree copy inconsistency, trying per-class decompilation");
for (ClassNode cls : jadxDecompiler.getClasses()) {
try {
jadxDecompiler.decompileClass(cls);
} catch (JadxRuntimeException ex) {
LOG.warn("Skipped: {}", cls.getFullName());
}
}
} else {
throw e;
}
} Prevention
- Keep jadx updated — block tree copy logic is periodically refined
- Try disabling inlining passes if available (e.g., --no-inline-anonymous)
- Report the APK as a jadx issue with the full stack trace
- Decompile classes individually to isolate the trigger
When it happens
Trigger: During copyBlocksTree, getNewBlock(successor, map) returns null because the successor BlockNode was not included in the initial map population. This means the source block graph has a successor that wasn't registered for copying.
Common situations: Internal inconsistency in the block graph during duplication; a block was added or modified between map creation and successor traversal; typically triggered during JSR/RET resolution or method inlining on complex control flow.
Related errors
- Failed to find top block for try-catch from: {}
- Unreachable block: {}
- Try blocks wrapping queue limit reached! Please report as an
- Unexpected missing predecessor for block: {}
- Missing block: {}
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/590af8b9c4932f11.
Report an issue: GitHub.