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

  1. Update jadx; exception-region invariants are hardened over releases.
  2. Report the input with the handler block from the message.
  3. Skip the affected class/method and continue the batch.
  4. 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

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


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