pxb1988/dex2jar · error · RuntimeException

can't parse type list:

Error message

can't parse type list: 

What it means

Types.listDesc walks a descriptor string character by character, expecting primitive/array/object type markers. When it meets a character that is not a recognized type-start token it throws RuntimeException("can't parse type list: " + desc), meaning the type-list descriptor contains an illegal character.

Solutions

  1. Erase generics first: use only standard JVM type descriptors (I, J, [Ljava/lang/String;, etc.) in the type list
  2. Strip generic signature tokens (<...>, T...) or parse with a signature parser instead of listDesc
  3. Inspect the appended desc in the message to find the illegal character and its origin
  4. If descriptors come from a dex/APK, re-extract from a known-good build — corruption or an exotic obfuscator may be at fault

Example fix

// before
Types.listDesc("Ljava/util/List<Ljava/lang/String;>;"); // throws
// after
Types.listDesc("Ljava/util/List;"); // erased descriptor parses fine
Defensive patterns

Strategy: validation

Validate before calling

private static final String TYPE_START = "BCDFIJSZL[";
public static void requirePlainTypeList(String desc) {
    if (desc == null || desc.indexOf('<') >= 0 || desc.indexOf('T') >= 0)
        throw new IllegalArgumentException("generic or invalid type list: " + desc);
    for (int i = 0; i < desc.length(); i++) {
        if (TYPE_START.indexOf(desc.charAt(i)) < 0)
            throw new IllegalArgumentException("illegal char in type list: " + desc);
    }
}

Type guard

static boolean isPlainDescriptor(String s) {
    return s != null && !s.isEmpty() && s.matches("([BCDFIJSZ\[]+|L[a-zA-Z0-9/_$]+;|[BCDFIJSZ\[\]|L;])*");
}

Try / catch

try {
    Types.listDesc(desc);
} catch (RuntimeException e) {
    if (e.getMessage().startsWith("can't parse type list")) {
        // erase generics / sanitize the descriptor before retrying
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling Types.listDesc(desc) — directly or via Types.getParameterTypeDesc — with a segment containing unsupported characters, e.g. generic signatures with '<'/'T' tokens, stray text, or corrupted type descriptors inside a method desc's parameter section.

Common situations: Passing a Java generic signature like '(Ljava/util/List<Ljava/lang/String;>;)V' where the code expects an erased descriptor; corrupted dex descriptors; hand-built desc strings with typos; parsing output of tools that emit non-erased signatures.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of pxb1988/dex2jar@b5bda4fb49 (2026-09-08). Data as JSON: /api/errors/59871a18e5f5af64. Report an issue: GitHub.

Appendix: source

Thrown at dex-translator/src/main/java/com/googlecode/d2j/util/Types.java:89

                    }
                }
                count++;
                list.add(new String(chars, i, count));
                i += count;
                break;
            }
            case 'L': {
                int count = 1;
                while (chars[i + count] != ';') {
                    ++count;
                }
                count++;
                list.add(new String(chars, i, count));
                i += count;
                break;
            }
            default:
                throw new RuntimeException("can't parse type list: " + desc);
            }
        }
        return list;
    }

    public static Object[] buildDexStyleSignature(String signature) {
        int rawLength = signature.length();
        ArrayList<String> pieces = new ArrayList<String>(20);

        for (int at = 0; at < rawLength; /* at */) {
            char c = signature.charAt(at);
            int endAt = at + 1;
            if (c == 'L') {
                // Scan to ';' or '<'. Consume ';' but not '<'.
                while (endAt < rawLength) {
                    c = signature.charAt(endAt);
                    if (c == ';') {
                        endAt++;

View on GitHub (pinned to b5bda4fb49)