skylot/jadx · critical · JadxRuntimeException

A state of class {} has duplicated to produce a class of {}

Error message

A state of class {} has duplicated to produce a class of {}

What it means

Thrown in DuplicatedTraverserStateFactory when duplicating a traverser state. The factory captures the base state's class, calls duplicate(), and verifies the duplicate is the same class. If duplicate() returns a different runtime class, the duplication contract is violated and the cast would be unsafe.

Source

Thrown at jadx-core/src/main/java/jadx/core/dex/visitors/finaly/traverser/factory/DuplicatedTraverserStateFactory.java:20

import jadx.core.dex.visitors.finaly.traverser.state.TraverserActivePathState;
import jadx.core.dex.visitors.finaly.traverser.state.TraverserState;
import jadx.core.utils.exceptions.JadxRuntimeException;

public final class DuplicatedTraverserStateFactory<T extends TraverserState> extends TraverserStateFactory<T> {
	private final T baseState;

	public DuplicatedTraverserStateFactory(T baseState) {
		this.baseState = baseState;
	}

	@SuppressWarnings("unchecked")
	@Override
	public T generateInternalState(TraverserActivePathState state) {
		Class<? extends T> baseStateClass = (Class<? extends T>) baseState.getClass();
		TraverserState duplicated = baseState.duplicate(state);
		if (!baseStateClass.isInstance(duplicated)) {
			throw new JadxRuntimeException(
					"A state of class " + baseState.getClass() + " has duplicated to produce a class of " + duplicated.getClass());
		}
		return baseStateClass.cast(duplicated);
	}

}

View on GitHub (pinned to e738a26571)

Solutions

  1. Update jadx — this is a development-time contract violation that will be patched
  2. Report as a jadx issue with the class names from the error message
  3. This cannot be triggered or resolved by user input; it requires a source fix in the state class
Defensive patterns

Strategy: try-catch

Try / catch

try {
    jadxDecompiler.load();
    jadxDecompiler.save();
} catch (JadxRuntimeException e) {
    if (e.getMessage().contains("duplicated to produce a class of")) {
        LOG.error("Internal jadx traverser state duplication bug — update jadx", e);
        for (ClassNode cls : jadxDecompiler.getClasses()) {
            try {
                jadxDecompiler.decompileClass(cls);
            } catch (JadxRuntimeException ex) {
                LOG.warn("Skipped: {}", cls.getFullName());
            }
        }
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: baseState.duplicate(state) returns a TraverserState whose runtime class differs from baseState.getClass(). The duplicate method's contract requires returning the same concrete type.

Common situations: A TraverserState subclass whose duplicate() method incorrectly instantiates a parent or sibling class instead of its own type; a refactoring that changed the class hierarchy without updating duplicate() implementations. This is a jadx internal development bug, not input-driven.

Related errors


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