skylot/jadx · error · JadxRuntimeException
Ordering pass not found: {}, listed in 'runBefore' of pass:
Error message
Ordering pass not found: {}, listed in 'runBefore' of pass: {}
all passes: {} What it means
Mirror of the runAfter case: PassMerge.searchInsertPos() iterates runBefore() and throws when a listed name is not found in the visitor position map and is not a known merge pass. The message names the missing pass, the pass that declared it, and the full pass list. Unlike runAfter, an unresolved runBefore name cannot be satisfied, so the pass cannot be positioned and the merge aborts.
Source
Thrown at jadx-core/src/main/java/jadx/core/utils/PassMerge.java:95
// ignore known passes
continue;
}
throw new JadxRuntimeException("Ordering pass not found: " + name
+ ", listed in 'runAfter' of pass: " + pass
+ "\n all passes: " + ListUtils.map(visitors, namesMap::get));
}
}
int before = Integer.MAX_VALUE;
for (String name : runBefore) {
Integer pos = namePosMap.get(name);
if (pos != null) {
before = Math.min(before, pos);
} else {
if (mergePassesNames.contains(name)) {
// ignore known passes
continue;
}
throw new JadxRuntimeException("Ordering pass not found: " + name
+ ", listed in 'runBefore' of pass: " + pass
+ "\n all passes: " + ListUtils.map(visitors, namesMap::get));
}
}
if (before <= after) {
throw new JadxRuntimeException("Conflict order requirements for pass: " + pass
+ "\n run after: " + runAfter
+ "\n run before: " + runBefore
+ "\n passes: " + ListUtils.map(visitors, namesMap::get));
}
if (after == -1) {
if (before == Integer.MAX_VALUE) {
// not ordered, put at last
return -1;
}
return before;
}
int pos = after + 1;View on GitHub (pinned to e738a26571)
Solutions
- Match the runBefore() name to an entry in the 'all passes:' list shown in the error.
- Align your plugin's jadx-api version with the running jadx to avoid referencing removed/renamed passes.
- If the target is a custom pass, make sure that pass's plugin is loaded (appears in mergePassesNames) before declaring runBefore.
- Use JadxPassInfo.END to run last, or remove the runBefore entry if strict ordering is unnecessary.
Example fix
// before
new JadxPassInfo("my-pass", "my pass").runBefore("ClassModifier"); // wrong name
// after
new JadxPassInfo("my-pass", "my pass").runBefore("ClassModifierVisitor"); // exact name Defensive patterns
Strategy: validation
Validate before calling
Set<String> known = visitors.stream().map(IDexTreeVisitor::getName).collect(Collectors.toSet());
for (String n : passInfo.runBefore()) {
if (!known.contains(n) && !mergePassNames.contains(n)
&& !JadxPassInfo.START.equals(n) && !JadxPassInfo.END.equals(n)) {
throw new IllegalArgumentException("runBefore references unknown pass: " + n);
}
} Try / catch
try {
passMerge.merge(customPasses, wrapFn);
} catch (JadxRuntimeException e) {
LOG.error("Pass merge failed (check runBefore names/version): {}", e.getMessage());
throw e;
} Prevention
- Keep plugin jadx-api version aligned with the running jadx.
- Derive pass names from source, not memory.
- After a jadx upgrade, re-validate your runBefore() names against the new pass list.
- Use START/END sentinels where strict ordering is unnecessary.
When it happens
Trigger: A custom JadxPass declares info().runBefore("foo") where "foo" is absent from built-in visitors and not a registered merge pass. Raised in the runBefore loop at PassMerge line 95.
Common situations: Version skew after a jadx upgrade that renamed/removed a pass you tried to run before; typo in runBefore(); depending on a custom pass that another (not-yet-loaded) plugin should have provided.
Related errors
- Ordering pass not found: {}, listed in 'runAfter' of pass: {
- Conflict order requirements for pass: {} run after: {} run
- Duplicate plugin id: {}, class {}
- Unknown type of resource file: ${resFile.getOriginalName()}
- Null option descriptions in plugin id: {}
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/0429f2e03a6f627e.
Report an issue: GitHub.