{"record":{"id":"9ec40f773d88c535","repo":"skylot/jadx","slug":"bad-name-for-type-variable","errorCode":null,"errorMessage":"Bad name for type variable: {}","messagePattern":"Bad name for type variable: (.+?)","errorType":"exception","errorClass":"JadxRuntimeException","httpStatus":null,"severity":"error","filePath":"jadx-core/src/main/java/jadx/core/dex/nodes/parser/SignatureParser.java","lineNumber":149,"sourceCode":"\t}\n\n\tpublic ArgType consumeType() {\n\t\tchar ch = next();\n\t\tswitch (ch) {\n\t\t\tcase 'L':\n\t\t\t\tArgType obj = consumeObjectType(false);\n\t\t\t\tif (obj != null) {\n\t\t\t\t\treturn obj;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'T':\n\t\t\t\tnext();\n\t\t\t\tmark();\n\t\t\t\tString typeVarName = consumeUntil(';');\n\t\t\t\tif (typeVarName != null) {\n\t\t\t\t\tconsume(';');\n\t\t\t\t\tif (typeVarName.contains(\")\")) {\n\t\t\t\t\t\tthrow new JadxRuntimeException(\"Bad name for type variable: \" + typeVarName);\n\t\t\t\t\t}\n\t\t\t\t\treturn ArgType.genericType(typeVarName);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase '[':\n\t\t\t\treturn ArgType.array(consumeType());\n\n\t\t\tcase STOP_CHAR:\n\t\t\t\treturn null;\n\n\t\t\tdefault:\n\t\t\t\t// primitive type (one char)\n\t\t\t\tArgType type = ArgType.parse(ch);\n\t\t\t\tif (type != null) {\n\t\t\t\t\treturn type;\n\t\t\t\t}\n\t\t\t\tbreak;","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-core/src/main/java/jadx/core/dex/nodes/parser/SignatureParser.java#L131-L167","documentation":"Thrown by SignatureParser when parsing a JVM generics type-variable reference (the 'T...;' form in a signature string) and the extracted variable name contains a ')' character. A well-formed type variable name is an identifier like 'T' or 'K'; a closing parenthesis indicates the parser has run past the end of the type-variable token into an enclosing method signature, i.e. the signature is malformed or was produced by an aggressive obfuscator. This is a defensive integrity check — jadx refuses to build a generic type from a name that is syntactically impossible in valid bytecode.","triggerScenarios":"consumeType() hits case 'T', calls consumeUntil(';'), gets a non-null string, then typeVarName.contains(\")\") is true. This happens when a class or method Signature attribute contains something like 'TT);' — a type variable token that leaks a paren, which violates the JVMS signature grammar.","commonSituations":"Decompiling APKs obfuscated by tools that corrupt or hand-craft Signature attributes (e.g. some variants of Allatori, custom obfuscators). Also seen with DEX files produced by non-standard compilers or bytecode rewriters that emit invalid generic signatures. Rare with stock javac/d8/r8 output.","solutions":["Upgrade to the latest jadx release — signature-parser robustness improvements land frequently and may make this a recoverable warning instead of a crash.","If using jadx as a library, catch JadxRuntimeException around the per-class decompilation call and skip the offending class so the batch continues.","Reproduce with the minimal APK/DEX and file a jadx issue including the full signature string from the error message so the parser can be hardened.","As a stopgap, strip the Signature attribute from the offending class with a bytecode editor (e.g. ASM) before decompiling, trading generics info for a successful decompile."],"exampleFix":"// before — unguarded decompile call\nfor (JavaClass cls : jadx.getClasses()) {\n    String code = cls.getCode();\n}\n\n// after — skip class on parser failure\nfor (JavaClass cls : jadx.getClasses()) {\n    try {\n        String code = cls.getCode();\n    } catch (JadxRuntimeException e) {\n        LOG.warn(\"Skipping {}: {}\", cls.getName(), e.getMessage());\n    }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Wrap per-class decompilation; malformed signatures are not preventable\nfor (JavaClass cls : jadx.getClasses()) {\n    try {\n        String code = cls.getCode();\n        results.put(cls.getName(), code);\n    } catch (JadxRuntimeException e) {\n        LOG.warn(\"Signature parse error in {}: {}\", cls.getName(), e.getMessage());\n    }\n}","preventionTips":["Use the latest jadx version — signature-parser robustness improves each release.","Process classes individually with try-catch rather than calling jadx.save() on the whole batch unguarded.","Validate input DEX/JAR files with dexdump or baksmali before decompiling to catch gross corruption early.","Keep the original APK so you can file reproducible bug reports with the failing class."],"tags":["jadx","decompiler","signature-parser","generics","obfuscation","bytecode"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}