skylot/jadx · error · JadxRuntimeException
Unexpected end of signature
Error message
Unexpected end of signature
What it means
Thrown by consumeExtendsTypesList() while parsing the bound(s) of a generic type parameter (the part after ':' in '<T:Ljava/lang/Exception;:Ljava/lang/Object;>'). If consumeType() returns null — meaning the signature ended where a type was expected — the method aborts. This indicates the bound list is truncated.
Source
Thrown at jadx-core/src/main/java/jadx/core/dex/nodes/parser/SignatureParser.java:311
List<ArgType> types = consumeExtendsTypesList();
list.add(ArgType.genericType(id, types));
}
consume('>');
return list;
}
/**
* List of types separated by ':' last type is 'java.lang.Object'.
* <p/>
* Example: "Ljava/lang/Exception;:Ljava/lang/Object;"
*/
private List<ArgType> consumeExtendsTypesList() {
List<ArgType> types = Collections.emptyList();
boolean next;
do {
ArgType argType = consumeType();
if (argType == null) {
throw new JadxRuntimeException("Unexpected end of signature");
}
if (!argType.equals(ArgType.OBJECT)) {
if (types.isEmpty()) {
types = new ArrayList<>();
}
types.add(argType);
}
next = lookAhead(':');
if (next) {
consume(':');
}
} while (next);
return types;
}
public List<ArgType> consumeMethodArgs(int argsCount) {
consume('(');
if (lookAhead(')')) {View on GitHub (pinned to e738a26571)
Solutions
- Upgrade jadx for improved parser resilience.
- Catch JadxRuntimeException per class and skip the failing one.
- Report with the signature debug string from the error.
- Remove the malformed Signature attribute before decompiling.
Defensive patterns
Strategy: try-catch
Try / catch
try {
javaClass.decompile();
} catch (JadxRuntimeException e) {
LOG.warn("Type-bound parse failed in {}: {}", javaClass.getName(), e.getMessage());
} Prevention
- Upgrade jadx for parser resilience.
- Isolate failures with per-class try-catch.
- Report truncated bound signatures with full context.
- Remove Signature attributes from failing classes as a workaround.
When it happens
Trigger: Inside consumeExtendsTypesList(), the do-while loop calls consumeType() which returns null (STOP_CHAR reached). This happens when a generic bound like ':Lcom/Foo;' is missing its type, e.g. '<T:' with nothing after the colon.
Common situations: Truncated or malformed type-parameter bounds in Signature attributes from obfuscators, hand-edited bytecode, or buggy DEX processing tools.
Related errors
- Bad name for type variable: {}
- No inner type found: {}
- Unexpected inner type found: {}
- Failed to parse generic types map
- Can't parse type: {}, unexpected: {}
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/d9e7f9685b3d50cf.
Report an issue: GitHub.