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

  1. Ensure ClsSet.loadFrom is not called concurrently from multiple threads on the same RootNode.
  2. Check for any custom modifications to ArgType that could make getObject() return inconsistent values across calls.
  3. Report as a jadx internal bug with the class name and input that reproduces it — this is an invariant violation.
  4. 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

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


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