{"record":{"id":"0f6b800f6d2f4efe","repo":"skylot/jadx","slug":"iterative-traversal-limit-reached-limit-visi","errorCode":null,"errorMessage":"Iterative traversal limit reached: limit: {}, visitor: {}, blocks count: {}","messagePattern":"Iterative traversal limit reached: limit: (.+?), visitor: (.+?), blocks count: (.+?)","errorType":"exception","errorClass":"JadxRuntimeException","httpStatus":null,"severity":"error","filePath":"jadx-core/src/main/java/jadx/core/dex/visitors/regions/DepthRegionTraversal.java","lineNumber":49,"sourceCode":"\t\ttraverseInternal(mth, visitor, container);\n\t}\n\n\tpublic static <R> @Nullable R traversePartial(MethodNode mth, IRegionPartialVisitor<R> visitor) {\n\t\treturn traversePartialInternal(mth, visitor, mth.getRegion());\n\t}\n\n\tpublic static <R> @Nullable R traversePartial(MethodNode mth, IContainer container, IRegionPartialVisitor<R> visitor) {\n\t\treturn traversePartialInternal(mth, visitor, container);\n\t}\n\n\tpublic static void traverseIterative(MethodNode mth, IRegionIterativeVisitor visitor) {\n\t\tboolean repeat;\n\t\tint k = 0;\n\t\tint limit = ITERATIVE_LIMIT_MULTIPLIER * mth.getBasicBlocks().size();\n\t\tdo {\n\t\t\trepeat = traverseIterativeStepInternal(mth, visitor, mth.getRegion());\n\t\t\tif (k++ > limit) {\n\t\t\t\tthrow new JadxRuntimeException(\"Iterative traversal limit reached: \"\n\t\t\t\t\t\t+ \"limit: \" + limit + \", visitor: \" + visitor.getClass().getName()\n\t\t\t\t\t\t+ \", blocks count: \" + mth.getBasicBlocks().size());\n\t\t\t}\n\t\t} while (repeat);\n\t}\n\n\tpublic static void traverseIncludingExcHandlers(MethodNode mth, IRegionIterativeVisitor visitor) {\n\t\tboolean repeat;\n\t\tint k = 0;\n\t\tint limit = ITERATIVE_LIMIT_MULTIPLIER * mth.getBasicBlocks().size();\n\t\tdo {\n\t\t\trepeat = traverseIterativeStepInternal(mth, visitor, mth.getRegion());\n\t\t\tif (!repeat) {\n\t\t\t\tfor (ExceptionHandler h : mth.getExceptionHandlers()) {\n\t\t\t\t\trepeat = traverseIterativeStepInternal(mth, visitor, h.getHandlerRegion());\n\t\t\t\t\tif (repeat) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-core/src/main/java/jadx/core/dex/visitors/regions/DepthRegionTraversal.java#L31-L67","documentation":"Thrown as JadxRuntimeException by DepthRegionTraversal.traverseIterative() (and traverseIncludingExcHandlers) when an iterative region visitor requests re-traversal more than 5 times the number of basic blocks in the method. Iterative visitors return a boolean 'repeat' indicating they made structural changes and want another pass; a limit prevents infinite loops from visitors that always report changes. The limit is ITERATIVE_LIMIT_MULTIPLIER (5) multiplied by the method's basic block count.","triggerScenarios":"An IRegionIterativeVisitor's visit method returns true (repeat) on every pass without converging, exceeding the 5 * blockCount limit. This typically happens with visitors that make progress-detected-incorrect changes (oscillating between two states) or visitors that unconditionally return true.","commonSituations":"Decompiling heavily obfuscated bytecode, malformed DEX files, or code with pathological control flow (deeply nested loops, large switch statements, exception-heavy code) that causes a region visitor to fail to converge. Common with R8/ProGuard-obfuscated APKs. The error message identifies the specific visitor class and block count for diagnosis.","solutions":["Report to jadx developers with the input file, the visitor class name from the error message, and the block count.","Try the latest jadx version — convergence bugs in region visitors are frequently patched.","As a workaround, use --decompilation-mode that uses simpler region processing, or skip specific visitors via debug flags.","If developing jadx, inspect the named visitor class for oscillation bugs — ensure it returns true only when it actually made a net structural change."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    DepthRegionTraversal.traverseIterative(mth, visitor);\n} catch (JadxRuntimeException e) {\n    if (e.getMessage().contains(\"Iterative traversal limit reached\")) {\n        LOG.warn(\"Visitor {} did not converge for method {} ({} blocks), skipping\",\n            visitor.getClass().getSimpleName(), mth, mth.getBasicBlocks().size());\n        // Continue decompilation without this visitor's transformations\n    } else {\n        throw e;\n    }\n}","preventionTips":["This is primarily triggered by problematic/obfuscated bytecode; keep jadx updated.","If developing jadx region visitors, ensure visit() returns true only on actual structural change, never unconditionally.","Test visitors on obfuscated inputs to check convergence.","Report inputs that trigger this with the visitor class name from the error message."],"tags":["jadx","decompiler","region-traversal","infinite-loop-guard","convergence-failure","obfuscation"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}