skylot/jadx · error · JadxRuntimeException
Orphaned TraverserState node
Error message
Orphaned TraverserState node
What it means
Thrown by TraverserActivePathState.getGlobalStateFor(TraverserState state) when the state argument is not the object currently held by either finallyStateRef or candidateStateRef. The method uses reference identity (==) to map a state to its global state group. This fires when a caller passes a state that is a duplicate or stale copy rather than the exact reference the active path currently holds.
Source
Thrown at jadx-core/src/main/java/jadx/core/dex/visitors/finaly/traverser/state/TraverserActivePathState.java:331
@Nullable
public final AtomicReference<TraverserState> getReferenceForState(TraverserState state) {
if (finallyStateRef.get() == state) {
return finallyStateRef;
}
if (candidateStateRef.get() == state) {
return candidateStateRef;
}
return null;
}
public final GlobalTraverserSourceState getGlobalStateFor(TraverserState state) {
if (finallyStateRef.get() == state) {
return finallyGlobalState;
}
if (candidateStateRef.get() == state) {
return candidateGlobalState;
}
throw new JadxRuntimeException("Orphaned TraverserState node");
}
public final GlobalTraverserSourceState getFinallyGlobalState() {
return finallyGlobalState;
}
public final GlobalTraverserSourceState getCandidateGlobalState() {
return candidateGlobalState;
}
public final TraverserGlobalCommonState getGlobalCommonState() {
return commonGlobalState;
}
public final void mergeWith(List<TraverserActivePathState> otherStates) {
for (TraverserActivePathState otherState : otherStates) {
matchedInsns.addAll(otherState.getMatchedInsns());
View on GitHub (pinned to e738a26571)
Solutions
- Report to jadx developers with the input file and full trace.
- Workaround: skip the finally visitor.
- If patching jadx, ensure that after every produceFromFactories() or duplicate() call, no stale state references are retained in handler queues or visitor-local variables.
Defensive patterns
Strategy: validation
Prevention
- Reference-identity invariant; only the exact object held by finallyStateRef or candidateStateRef is valid.
- If developing jadx, never query global state on a duplicated/stale state; always use the current reference from the active path.
- Report inputs that trigger this with the full stack trace.
When it happens
Trigger: Called via TraverserState.getGlobalState() which delegates to getComparatorState().getGlobalStateFor(this). If 'this' is a duplicated state whose comparatorState points to an active path that holds a different state object in its slot, the identity check fails.
Common situations: State duplication during merge or branch operations produces a new state object, but an old reference to the pre-duplication state is still used to query global state. Happens with deeply nested finally blocks or synchronized regions.
Related errors
- Unknown global traverser state. Has a global state been dupl
- Expected to find block info within {}
- Orphaned traverser state
- Orphaned traverser state
- Attempted to get instructions slice of block {} with {} skip
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/599632474336ffd5.
Report an issue: GitHub.