{"record":{"id":"c60041eba7c2ca5b","repo":"skylot/jadx","slug":"a-state-of-class-has-duplicated-to-produce-a-cl","errorCode":null,"errorMessage":"A state of class {} has duplicated to produce a class of {}","messagePattern":"A state of class (.+?) has duplicated to produce a class of (.+?)","errorType":"exception","errorClass":"JadxRuntimeException","httpStatus":null,"severity":"critical","filePath":"jadx-core/src/main/java/jadx/core/dex/visitors/finaly/traverser/factory/DuplicatedTraverserStateFactory.java","lineNumber":20,"sourceCode":"\nimport jadx.core.dex.visitors.finaly.traverser.state.TraverserActivePathState;\nimport jadx.core.dex.visitors.finaly.traverser.state.TraverserState;\nimport jadx.core.utils.exceptions.JadxRuntimeException;\n\npublic final class DuplicatedTraverserStateFactory<T extends TraverserState> extends TraverserStateFactory<T> {\n\tprivate final T baseState;\n\n\tpublic DuplicatedTraverserStateFactory(T baseState) {\n\t\tthis.baseState = baseState;\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\t@Override\n\tpublic T generateInternalState(TraverserActivePathState state) {\n\t\tClass<? extends T> baseStateClass = (Class<? extends T>) baseState.getClass();\n\t\tTraverserState duplicated = baseState.duplicate(state);\n\t\tif (!baseStateClass.isInstance(duplicated)) {\n\t\t\tthrow new JadxRuntimeException(\n\t\t\t\t\t\"A state of class \" + baseState.getClass() + \" has duplicated to produce a class of \" + duplicated.getClass());\n\t\t}\n\t\treturn baseStateClass.cast(duplicated);\n\t}\n\n}\n","sourceCodeStart":2,"sourceCodeEnd":27,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-core/src/main/java/jadx/core/dex/visitors/finaly/traverser/factory/DuplicatedTraverserStateFactory.java#L2-L27","documentation":"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.","triggerScenarios":"baseState.duplicate(state) returns a TraverserState whose runtime class differs from baseState.getClass(). The duplicate method's contract requires returning the same concrete type.","commonSituations":"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.","solutions":["Update jadx — this is a development-time contract violation that will be patched","Report as a jadx issue with the class names from the error message","This cannot be triggered or resolved by user input; it requires a source fix in the state class"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    jadxDecompiler.load();\n    jadxDecompiler.save();\n} catch (JadxRuntimeException e) {\n    if (e.getMessage().contains(\"duplicated to produce a class of\")) {\n        LOG.error(\"Internal jadx traverser state duplication bug — update jadx\", e);\n        for (ClassNode cls : jadxDecompiler.getClasses()) {\n            try {\n                jadxDecompiler.decompileClass(cls);\n            } catch (JadxRuntimeException ex) {\n                LOG.warn(\"Skipped: {}\", cls.getFullName());\n            }\n        }\n    } else {\n        throw e;\n    }\n}","preventionTips":["Update jadx — this is a state duplication contract violation that will be patched","Report as a jadx issue with the class names from the error message","Decompile classes individually to isolate and skip the problematic class","Use an alternative decompiler as fallback for the affected class"],"tags":["traverser","internal-bug","state-duplication","finally-block","decompiler"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}