skylot/jadx · error · JadxRuntimeException
Not class type: {}
Error message
Not class type: {} What it means
Thrown by ClassInfo.checkClassType when the ArgType is non-null but is neither an object type nor is a generic type (type.isObject() false, or type.isGenericType() true). It enforces that a ClassInfo only describes a concrete class type, not a primitive, a bare type variable, or an unparameterised generic.
Source
Thrown at jadx-core/src/main/java/jadx/core/dex/info/ClassInfo.java:59
public static ClassInfo fromName(RootNode root, String clsName) {
return fromType(root, ArgType.object(clsName));
}
public static ClassInfo fromNameWithoutCache(RootNode root, String fullClsName, boolean canBeInner) {
return new ClassInfo(root, ArgType.object(fullClsName), canBeInner);
}
private static ArgType checkClassType(ArgType type) {
if (type == null) {
throw new JadxRuntimeException("Null class type");
}
if (type.isArray()) {
// TODO: check case with method declared in array class like ( clone in int[])
return ArgType.OBJECT;
}
if (!type.isObject() || type.isGenericType()) {
throw new JadxRuntimeException("Not class type: " + type);
}
if (type.isGeneric()) {
return ArgType.object(type.getObject());
}
return type;
}
public void changeShortName(String aliasName) {
ClassAliasInfo newAlias;
String aliasPkg = getAliasPkg();
if (Objects.equals(name, aliasName) || StringUtils.isEmpty(aliasName)) {
if (Objects.equals(getPackage(), aliasPkg)) {
newAlias = null;
} else {
newAlias = new ClassAliasInfo(aliasPkg, name);
}
} else {
newAlias = new ClassAliasInfo(aliasPkg, aliasName);View on GitHub (pinned to e738a26571)
Solutions
- Before building ClassInfo, check type.isObject() && !type.isGenericType(); if not, handle via the appropriate (generic/primitive) path instead.
- For generic types, extract the raw object type first: ArgType.object(type.getObject()).
- Inspect the offending ArgType (printed in the message) to see why it is not a class type.
- Fix the upstream descriptor/type parsing that produced the wrong kind.
Example fix
// before
ClassInfo info = ClassInfo.fromType(root, type); // throws for primitives/generics
// after
if (type == null) {
return null;
}
if (!type.isObject() || type.isGenericType()) {
if (type.isGeneric()) {
type = ArgType.object(type.getObject()); // use raw type
} else {
throw new IllegalArgumentException("Not a class type: " + type);
}
}
ClassInfo info = ClassInfo.fromType(root, type); Defensive patterns
Strategy: type-guard
Validate before calling
if (type == null || !type.isObject() || type.isGenericType()) {
if (type != null && type.isGeneric()) {
type = ArgType.object(type.getObject()); // use raw type
} else {
throw new IllegalArgumentException("Not a class type: " + type);
}
} Type guard
static boolean isClassType(ArgType t) {
return t != null && t.isObject() && !t.isGenericType();
} Try / catch
try {
return ClassInfo.fromType(root, type);
} catch (JadxRuntimeException e) {
if (type != null && type.isGeneric()) {
return ClassInfo.fromType(root, ArgType.object(type.getObject()));
}
throw e;
} Prevention
- For generics, extract the raw object type before class-info lookup.
- Validate isObject() && !isGenericType() at the call site.
- Route primitives and type variables through their own resolution paths.
When it happens
Trigger: Passing an ArgType that is a primitive (INT, etc.), a type variable (e.g. T), or a generic-type-token where a concrete class is required. Happens when class resolution is fed a type that does not denote an actual class.
Common situations: Misrouting generic/type-variable resolution into class-info lookup; parsing a type descriptor incorrectly so it is not recognised as OBJECT; obfuscated descriptors that resolve to a generic instead of a class.
Related errors
- Null class type
- Can't change package for inner class: {}
- Can't change package for inner class
- Unknown type in literalToString:
- Class alias can't be empty
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/fe679f99116641e1.
Report an issue: GitHub.