{"record":{"id":"54761eeccebb11a9","repo":"skylot/jadx","slug":"conflict-order-requirements-for-pass-run-afte","errorCode":null,"errorMessage":"Conflict order requirements for pass: {}\n run after: {}\n run before: {}\n passes: {}","messagePattern":"Conflict order requirements for pass: (.+?)\n run after: (.+?)\n run before: (.+?)\n passes: (.+?)","errorType":"exception","errorClass":"JadxRuntimeException","httpStatus":null,"severity":"error","filePath":"jadx-core/src/main/java/jadx/core/utils/PassMerge.java","lineNumber":101,"sourceCode":"\t\t\t}\n\t\t}\n\t\tint before = Integer.MAX_VALUE;\n\t\tfor (String name : runBefore) {\n\t\t\tInteger pos = namePosMap.get(name);\n\t\t\tif (pos != null) {\n\t\t\t\tbefore = Math.min(before, pos);\n\t\t\t} else {\n\t\t\t\tif (mergePassesNames.contains(name)) {\n\t\t\t\t\t// ignore known passes\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthrow new JadxRuntimeException(\"Ordering pass not found: \" + name\n\t\t\t\t\t\t+ \", listed in 'runBefore' of pass: \" + pass\n\t\t\t\t\t\t+ \"\\n all passes: \" + ListUtils.map(visitors, namesMap::get));\n\t\t\t}\n\t\t}\n\t\tif (before <= after) {\n\t\t\tthrow new JadxRuntimeException(\"Conflict order requirements for pass: \" + pass\n\t\t\t\t\t+ \"\\n run after: \" + runAfter\n\t\t\t\t\t+ \"\\n run before: \" + runBefore\n\t\t\t\t\t+ \"\\n passes: \" + ListUtils.map(visitors, namesMap::get));\n\t\t}\n\t\tif (after == -1) {\n\t\t\tif (before == Integer.MAX_VALUE) {\n\t\t\t\t// not ordered, put at last\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\treturn before;\n\t\t}\n\t\tint pos = after + 1;\n\t\treturn pos >= visitorsCount ? -1 : pos;\n\t}\n\n\tprivate static final class MergePass {\n\t\tprivate final JadxPass pass;\n\t\tprivate final IDexTreeVisitor visitor;","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-core/src/main/java/jadx/core/utils/PassMerge.java#L83-L119","documentation":"Thrown by PassMerge when a pass's combined runAfter and runBefore constraints are unsatisfiable: the latest 'after' position is >= the earliest 'before' position (before <= after). The pass would have to run both after something that sits at or past where it must run before. The message dumps the pass, its runAfter/runBefore lists, and the full ordered pass list so you can see the conflict.","triggerScenarios":"A JadxPass declares runAfter(A) and runBefore(B) but A is positioned at or after B in the visitor order (e.g. runAfter a late pass while runBefore an early one), so no legal insertion index exists.","commonSituations":"Conflicting ordering hints added independently (one pass wants to run after the rename pass but before an early pass that precedes rename); version skew changing relative positions of built-in passes; a transitive ordering cycle between multiple custom passes.","solutions":["Inspect the 'passes:' order in the message and relax whichever constraint (runAfter or runBefore) is wrong for your pass's intent.","Keep only one directional constraint if you do not need to pin both sides.","Re-resolve names against the current jadx build so positions reflect reality.","If multiple custom passes conflict, ensure their runAfter/runBefore form a DAG (no cycle) and re-run."],"exampleFix":"// before - runAfter late pass, runBefore early pass => before <= after\nnew JadxPassInfo(\"p\", \"p\").runAfter(\"RenameVisitor\").runBefore(\"EarlyVisitor\");\n// after - keep a single satisfiable constraint\nnew JadxPassInfo(\"p\", \"p\").runAfter(\"RenameVisitor\");","handlingStrategy":"validation","validationCode":"// After resolving positions, verify runAfter/runBefore are jointly satisfiable.\nint after = maxResolvedPos(runAfter);   // -1 if none\nint before = minResolvedPos(runBefore); // MAX_VALUE if none\nif (after >= 0 && before != Integer.MAX_VALUE && before <= after) {\n    throw new IllegalArgumentException(\n        \"Unsatisfiable ordering: runAfter pos=\" + after + \" >= runBefore pos=\" + before);\n}","typeGuard":null,"tryCatchPattern":"try {\n    passMerge.merge(customPasses, wrapFn);\n} catch (JadxRuntimeException e) {\n    if (e.getMessage().contains(\"Conflict order requirements\")) {\n        LOG.warn(\"Conflicting pass order, dropping custom pass: {}\", e.getMessage());\n    } else {\n        throw e;\n    }\n}","preventionTips":["Declare only one directional constraint unless you genuinely need both.","Check that runAfter targets sit strictly before runBefore targets in the live order.","Avoid ordering cycles between multiple custom passes.","Re-validate constraints after a jadx upgrade changes built-in pass positions."],"tags":["jadx","plugins","pass-ordering","configuration"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}