{"record":{"id":"d9e7f9685b3d50cf","repo":"skylot/jadx","slug":"unexpected-end-of-signature","errorCode":null,"errorMessage":"Unexpected end of signature","messagePattern":"Unexpected end of signature","errorType":"exception","errorClass":"JadxRuntimeException","httpStatus":null,"severity":"error","filePath":"jadx-core/src/main/java/jadx/core/dex/nodes/parser/SignatureParser.java","lineNumber":311,"sourceCode":"\t\t\tList<ArgType> types = consumeExtendsTypesList();\n\t\t\tlist.add(ArgType.genericType(id, types));\n\t\t}\n\t\tconsume('>');\n\t\treturn list;\n\t}\n\n\t/**\n\t * List of types separated by ':' last type is 'java.lang.Object'.\n\t * <p/>\n\t * Example: \"Ljava/lang/Exception;:Ljava/lang/Object;\"\n\t */\n\tprivate List<ArgType> consumeExtendsTypesList() {\n\t\tList<ArgType> types = Collections.emptyList();\n\t\tboolean next;\n\t\tdo {\n\t\t\tArgType argType = consumeType();\n\t\t\tif (argType == null) {\n\t\t\t\tthrow new JadxRuntimeException(\"Unexpected end of signature\");\n\t\t\t}\n\t\t\tif (!argType.equals(ArgType.OBJECT)) {\n\t\t\t\tif (types.isEmpty()) {\n\t\t\t\t\ttypes = new ArrayList<>();\n\t\t\t\t}\n\t\t\t\ttypes.add(argType);\n\t\t\t}\n\t\t\tnext = lookAhead(':');\n\t\t\tif (next) {\n\t\t\t\tconsume(':');\n\t\t\t}\n\t\t} while (next);\n\t\treturn types;\n\t}\n\n\tpublic List<ArgType> consumeMethodArgs(int argsCount) {\n\t\tconsume('(');\n\t\tif (lookAhead(')')) {","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-core/src/main/java/jadx/core/dex/nodes/parser/SignatureParser.java#L293-L329","documentation":"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.","triggerScenarios":"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.","commonSituations":"Truncated or malformed type-parameter bounds in Signature attributes from obfuscators, hand-edited bytecode, or buggy DEX processing tools.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    javaClass.decompile();\n} catch (JadxRuntimeException e) {\n    LOG.warn(\"Type-bound parse failed in {}: {}\", javaClass.getName(), e.getMessage());\n}","preventionTips":["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."],"tags":["jadx","decompiler","signature-parser","generics","type-bound","obfuscation"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}