{"record":{"id":"f2c674334d2ced76","repo":"skylot/jadx","slug":"can-t-find-top-splitter-block-for-handler","errorCode":null,"errorMessage":"Can't find top splitter block for handler:{}","messagePattern":"Can't find top splitter block for handler:(.+?)","errorType":"exception","errorClass":"JadxRuntimeException","httpStatus":null,"severity":"error","filePath":"jadx-core/src/main/java/jadx/core/utils/BlockUtils.java","lineNumber":1478,"sourceCode":"\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t}\n\n\tpublic static boolean replaceInsn(MethodNode mth, InsnNode oldInsn, InsnNode newInsn) {\n\t\tfor (BlockNode block : mth.getBasicBlocks()) {\n\t\t\tif (replaceInsn(mth, block, oldInsn, newInsn)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic static BlockNode getTopSplitterForHandler(BlockNode handlerBlock) {\n\t\tBlockNode block = getBlockWithFlag(handlerBlock.getPredecessors(), AFlag.EXC_TOP_SPLITTER);\n\t\tif (block == null) {\n\t\t\tthrow new JadxRuntimeException(\"Can't find top splitter block for handler:\" + handlerBlock);\n\t\t}\n\t\treturn block;\n\t}\n\n\t/**\n\t * Return out block of try catch, by finding where try branch meets catch branch.\n\t * It traverse domFrontier start from handler block, find the first frontier\n\t * whose predecessor is try end.\n\t * <br>\n\t * It could return null if they never meets, but this doesn't mean that catch\n\t * ends at the method exit.\n\t * (see TestSwitchWithTryCatch and ExcHandlersRegionMaker#processExcHandler).\n\t */\n\t@Nullable\n\tpublic static BlockNode getTryAndHandlerCrossBlock(MethodNode mth, ExceptionHandler handler) {\n\t\tBlockNode start = handler.getHandlerBlock();\n\t\tBlockNode topSplitter = BlockUtils.getTopSplitterForHandler(start);\n\t\tList<ExceptionHandler> allHandlers = handler.getTryBlock().getHandlers();","sourceCodeStart":1460,"sourceCodeEnd":1496,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-core/src/main/java/jadx/core/utils/BlockUtils.java#L1460-L1496","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    BlockNode top = BlockUtils.getTopSplitterForHandler(handler);\n} catch (JadxRuntimeException e) {\n    LOG.warn(\"no EXC_TOP_SPLITTER for handler {}\", handler, e);\n}","preventionTips":["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."],"tags":["decompiler","exceptions","try-catch","regions","invariant-violation"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}