skylot/jadx · error · JadxRuntimeException
Classpath already loaded
Error message
Classpath already loaded
What it means
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.
Source
Thrown at jadx-core/src/main/java/jadx/core/clsp/ClspGraph.java:53
private final Set<String> missingClasses = new HashSet<>();
public ClspGraph(RootNode rootNode) {
this.root = rootNode;
}
public void loadClsSetFile() throws IOException, DecodeException {
ClsSet set = new ClsSet(root);
set.loadFromClstFile();
addClasspath(set);
}
public void addClasspath(ClsSet set) {
if (nameMap == null) {
nameMap = new HashMap<>(set.getClassesCount());
set.addToMap(nameMap);
} else {
throw new JadxRuntimeException("Classpath already loaded");
}
}
public void addApp(List<ClassNode> classes) {
if (nameMap == null) {
nameMap = new HashMap<>(classes.size());
}
for (ClassNode cls : classes) {
addClass(cls);
}
}
public void initCache() {
fillSuperTypesCache();
fillImplementsCache();
}
public boolean isClsKnown(String fullName) {View on GitHub (pinned to e738a26571)
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.
Example fix
// before
// graph.addClasspath(set1);
// graph.addClasspath(set2); // throws
// after
// if (graph.getNameMap() == null) {
// graph.addClasspath(set);
// } Defensive patterns
Strategy: validation
Validate before calling
// Check before adding classpath ClspGraph graph = root.getClspGraph(); // nameMap is private; use a guard method or ensure single initialization // Safest: create a fresh RootNode for each independent classpath load RootNode root = new RootNode(args); root.getClspGraph().loadClsSetFile(); // call exactly once // Do NOT call loadClsSetFile() or addClasspath() again on this root
Try / catch
try {
graph.addClasspath(set);
} catch (JadxRuntimeException e) {
if (e.getMessage().equals("Classpath already loaded")) {
logger.warn("Classpath already loaded on this graph, skipping.");
// Safe to ignore if the existing classpath is sufficient
} else {
throw e;
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Unsupported Arg Type:
- String is too long:
- String read error
- No loaded files
- Failed to init res table provider: ${resTableParserProvider}
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/c2703dedc596ba3c.
Report an issue: GitHub.