skylot/jadx · error · JadxRuntimeException
Missing class:
Error message
Missing class:
What it means
Thrown by ClsSet.loadFrom when getCls(cls, names) returns null for a class that was just added to the names map. This is an internal consistency check: every ClassNode in the input list should be retrievable from the names map built in the first loop. A null return indicates the map lookup failed for a class that should be present, which would imply a hash/key inconsistency or concurrent modification.
Source
Thrown at jadx-core/src/main/java/jadx/core/clsp/ClsSet.java:113
ArgType clsType = cls.getClassInfo().getType();
String clsRawName = clsType.getObject();
cls.load();
ClspClassSource source = getClspClassSource(cls);
ClspClass nClass = new ClspClass(clsType, k, cls.getAccessFlags().rawValue(), source);
if (names.put(clsRawName, nClass) != null) {
throw new JadxRuntimeException("Duplicate class: " + clsRawName);
}
k++;
nClass.setTypeParameters(cls.getGenericTypeParameters());
nClass.setMethods(getMethodsDetails(cls));
}
classes = new ClspClass[k];
k = 0;
for (ClassNode cls : list) {
ClspClass nClass = getCls(cls, names);
if (nClass == null) {
throw new JadxRuntimeException("Missing class: " + cls);
}
nClass.setParents(makeParentsArray(cls));
classes[k] = nClass;
k++;
}
}
private static ClspClassSource getClspClassSource(ClassNode cls) {
String inputFileName = cls.getClsData().getInputFileName();
int idx = inputFileName.indexOf(':');
String sourceFile = inputFileName.substring(0, idx);
ClspClassSource source = ClspClassSource.getClspClassSource(sourceFile);
if (source == ClspClassSource.APP) {
throw new JadxRuntimeException("Unexpected input file: " + inputFileName);
}
return source;
}
View on GitHub (pinned to e738a26571)
Solutions
- Ensure ClsSet.loadFrom is not called concurrently from multiple threads on the same RootNode.
- Check for any custom modifications to ArgType that could make getObject() return inconsistent values across calls.
- Report as a jadx internal bug with the class name and input that reproduces it — this is an invariant violation.
- As a workaround, retry the operation on a freshly loaded RootNode to rule out transient state corruption.
Defensive patterns
Strategy: try-catch
Try / catch
try {
clsSet.loadFrom(root);
} catch (JadxRuntimeException e) {
if (e.getMessage().startsWith("Missing class:")) {
LOG.error("Internal inconsistency: class lookup failed. This is likely a jadx bug.", e);
// retry on a fresh RootNode
} else {
throw e;
}
} Prevention
- Do not call ClsSet.loadFrom concurrently from multiple threads on the same RootNode.
- Report this as a jadx internal bug if it occurs — it indicates an invariant violation.
- Retry on a freshly loaded RootNode to rule out transient state corruption.
When it happens
Trigger: This error fires in the second loop of loadFrom where parents are assigned. getCls(cls, names) looks up by the class's raw name. A null return is theoretically impossible if the class was added in the first loop with the same key derivation, unless ArgType.getObject() returns a different value on the second call (mutable ArgType) or the map was concurrently modified.
Common situations: In practice, this is a defensive check that should never fire under normal operation. If it does, it indicates either a thread-safety issue (concurrent access to the RootNode during loadFrom), a bug in ArgType equality/hashing, or memory corruption. Extremely rare in production jadx usage.
Related errors
- Duplicate class:
- Cannot save type:
- Can't load classpath file:
- Unexpected input file:
- Unknown file format:
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/ff9548b88b3598ad.
Report an issue: GitHub.