{"record":{"id":"c2703dedc596ba3c","repo":"skylot/jadx","slug":"classpath-already-loaded","errorCode":null,"errorMessage":"Classpath already loaded","messagePattern":"Classpath already loaded","errorType":"exception","errorClass":"JadxRuntimeException","httpStatus":null,"severity":"error","filePath":"jadx-core/src/main/java/jadx/core/clsp/ClspGraph.java","lineNumber":53,"sourceCode":"\n\tprivate final Set<String> missingClasses = new HashSet<>();\n\n\tpublic ClspGraph(RootNode rootNode) {\n\t\tthis.root = rootNode;\n\t}\n\n\tpublic void loadClsSetFile() throws IOException, DecodeException {\n\t\tClsSet set = new ClsSet(root);\n\t\tset.loadFromClstFile();\n\t\taddClasspath(set);\n\t}\n\n\tpublic void addClasspath(ClsSet set) {\n\t\tif (nameMap == null) {\n\t\t\tnameMap = new HashMap<>(set.getClassesCount());\n\t\t\tset.addToMap(nameMap);\n\t\t} else {\n\t\t\tthrow new JadxRuntimeException(\"Classpath already loaded\");\n\t\t}\n\t}\n\n\tpublic void addApp(List<ClassNode> classes) {\n\t\tif (nameMap == null) {\n\t\t\tnameMap = new HashMap<>(classes.size());\n\t\t}\n\t\tfor (ClassNode cls : classes) {\n\t\t\taddClass(cls);\n\t\t}\n\t}\n\n\tpublic void initCache() {\n\t\tfillSuperTypesCache();\n\t\tfillImplementsCache();\n\t}\n\n\tpublic boolean isClsKnown(String fullName) {","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-core/src/main/java/jadx/core/clsp/ClspGraph.java#L35-L71","documentation":"Thrown by ClspGraph.addClasspath() when nameMap is already non-null, meaning a classpath ClsSet has already been registered on this ClspGraph instance. The classpath can only be loaded once; subsequent calls are rejected to prevent duplicate or conflicting class data.","triggerScenarios":"Calling addClasspath() or loadClsSetFile() twice on the same ClspGraph instance. This commonly happens in code that re-initializes a RootNode or attempts to merge multiple classpath sets into one graph.","commonSituations":"Reusing a JadxDecompiler or RootNode instance across multiple decompilation runs without resetting the ClspGraph. Plugin or integration code that loads the classpath eagerly and then the core also loads it.","solutions":["Create a new ClspGraph/RootNode instance for each independent classpath load.","Check whether nameMap is already populated before calling addClasspath() — guard the call with a null check.","Refactor the initialization flow to ensure loadClsSetFile() or addClasspath() is called exactly once per graph lifetime."],"exampleFix":"// before\n//   graph.addClasspath(set1);\n//   graph.addClasspath(set2); // throws\n// after\n//   if (graph.getNameMap() == null) {\n//       graph.addClasspath(set);\n//   }","handlingStrategy":"validation","validationCode":"// Check before adding classpath\nClspGraph graph = root.getClspGraph();\n// nameMap is private; use a guard method or ensure single initialization\n// Safest: create a fresh RootNode for each independent classpath load\nRootNode root = new RootNode(args);\nroot.getClspGraph().loadClsSetFile(); // call exactly once\n// Do NOT call loadClsSetFile() or addClasspath() again on this root","typeGuard":null,"tryCatchPattern":"try {\n    graph.addClasspath(set);\n} catch (JadxRuntimeException e) {\n    if (e.getMessage().equals(\"Classpath already loaded\")) {\n        logger.warn(\"Classpath already loaded on this graph, skipping.\");\n        // Safe to ignore if the existing classpath is sufficient\n    } else {\n        throw e;\n    }\n}","preventionTips":["Initialize the classpath exactly once per RootNode lifecycle.","Create a new RootNode/ClspGraph for each independent decompilation context.","Centralize classpath loading in a single initialization method to prevent duplicate calls."],"tags":["clsp","state","initialization","classpath"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}