skylot/jadx · error · JadxRuntimeException

Orphaned traverser state

Error message

Orphaned traverser state

What it means

Thrown by PredecessorBlockPathTraverserHandler.handle() when the active path's getReferenceForState(baseState) returns null. This is the same orphaned-state invariant as error 161 but in the predecessor-block traversal path: the handler walks backward from a source block, and it must be able to update the state slot that holds the current state. If the state is not the finally or candidate reference of its own comparator, the handler cannot write its result.

Source

Thrown at jadx-core/src/main/java/jadx/core/dex/visitors/finaly/traverser/handlers/PredecessorBlockPathTraverserHandler.java:33

	private final ISourceBlockState sourceBlockState;

	public PredecessorBlockPathTraverserHandler(T initialState) {
		super(initialState);
		this.sourceBlockState = initialState;
	}

	public PredecessorBlockPathTraverserHandler(AtomicReference<T> initialStateRef) {
		super(initialStateRef);
		this.sourceBlockState = initialStateRef.get();
	}

	@Override
	protected void handle() {
		TraverserState baseState = getState();
		TraverserActivePathState comparator = baseState.getComparatorState();
		AtomicReference<TraverserState> stateRef = comparator.getReferenceForState(baseState);
		if (stateRef == null) {
			throw new JadxRuntimeException("Orphaned traverser state");
		}
		BlockNode sourceBlock = sourceBlockState.getSourceBlock();
		AbstractBlockTraverserVisitor visitor = new PredecessorBlockTraverserVisitor(baseState);
		TraverserState nextState = visitor.visit(sourceBlock);

		stateRef.set(nextState);
	}
}

View on GitHub (pinned to e738a26571)

Solutions

  1. Report to the jadx project with the input and stack trace.
  2. Workaround: disable the finally extraction pass.
  3. If developing jadx, trace the state lifecycle from PredecessorBlockTraverserVisitor.visit() back through the controller to ensure the state dispatched is still the live reference held by the active path.
Defensive patterns

Strategy: validation

Validate before calling

AtomicReference<TraverserState> ref = comparator.getReferenceForState(baseState);
if (ref == null) {
    // Orphaned state; cannot update the slot
    return;
}

Prevention

When it happens

Trigger: A predecessor-walking handler is dispatched for a state that was already superseded by a new state set into the same AtomicReference slot, or the state's comparatorState back-pointer points to a different active path than expected.

Common situations: Decompiling code with backward-jumping control flow (loops, continue statements inside try-finally) where the predecessor traversal encounters a state that was already advanced or replaced by a concurrent branch.

Related errors


AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14). Data as JSON: /api/errors/50d6a74268122a73. Report an issue: GitHub.