skylot/jadx · error · JadxRuntimeException
Can't find top splitter block for handler:{}
Error message
Can't find top splitter block for handler:{} What it means
Thrown by BlockUtils.getTopSplitterForHandler when none of the handler block's predecessors carries AFlag.EXC_TOP_SPLITTER. The top splitter is the block that starts the 'try' range for an exception handler; the flag is set during exception-handler region making. Absence means the handler was reached without the try-catch splitter being marked, which violates jadx's exception-region invariant.
Source
Thrown at jadx-core/src/main/java/jadx/core/utils/BlockUtils.java:1478
return i;
}
}
return -1;
}
public static boolean replaceInsn(MethodNode mth, InsnNode oldInsn, InsnNode newInsn) {
for (BlockNode block : mth.getBasicBlocks()) {
if (replaceInsn(mth, block, oldInsn, newInsn)) {
return true;
}
}
return false;
}
public static BlockNode getTopSplitterForHandler(BlockNode handlerBlock) {
BlockNode block = getBlockWithFlag(handlerBlock.getPredecessors(), AFlag.EXC_TOP_SPLITTER);
if (block == null) {
throw new JadxRuntimeException("Can't find top splitter block for handler:" + handlerBlock);
}
return block;
}
/**
* Return out block of try catch, by finding where try branch meets catch branch.
* It traverse domFrontier start from handler block, find the first frontier
* whose predecessor is try end.
* <br>
* It could return null if they never meets, but this doesn't mean that catch
* ends at the method exit.
* (see TestSwitchWithTryCatch and ExcHandlersRegionMaker#processExcHandler).
*/
@Nullable
public static BlockNode getTryAndHandlerCrossBlock(MethodNode mth, ExceptionHandler handler) {
BlockNode start = handler.getHandlerBlock();
BlockNode topSplitter = BlockUtils.getTopSplitterForHandler(start);
List<ExceptionHandler> allHandlers = handler.getTryBlock().getHandlers();View on GitHub (pinned to e738a26571)
Solutions
- Update jadx; exception-region invariants are hardened over releases.
- Report the input with the handler block from the message.
- Skip the affected class/method and continue the batch.
- Catch JadxRuntimeException around per-method decompilation when embedding jadx.
Defensive patterns
Strategy: try-catch
Try / catch
try {
BlockNode top = BlockUtils.getTopSplitterForHandler(handler);
} catch (JadxRuntimeException e) {
LOG.warn("no EXC_TOP_SPLITTER for handler {}", handler, e);
} Prevention
- Update jadx; exception-region invariants are hardened over releases.
- Catch around getTopSplitterForHandler if your pass can tolerate a missing splitter.
- Report the input with the handler block from the message.
When it happens
Trigger: Calling getTopSplitterForHandler(handlerBlock) on a handler whose predecessor chain has no EXC_TOP_SPLITTER - e.g. after a pass removed/replaced the splitter, on a malformed exception table, or when the handler block was constructed synthetically without going through ExcHandlersRegionMaker.
Common situations: Reachable indirectly from getTryAndHandlerCrossBlock (used during region making). Usually a secondary effect of a prior exception-handling transform or of malformed exception metadata in the input. Rare on valid DEX.
Related errors
- Try blocks wrapping queue limit reached! Please report as an
- Failed to find top block for try-catch from: {}
- Same handlers in try block: {}
- Expected to find fallthrough terminus for handler {}
- Regions count limit reached at block {}
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/f2c674334d2ced76.
Report an issue: GitHub.