pxb1988/dex2jar · error · IOException

The source file is not a .dex or .zip file

Error message

The source file is not a .dex or .zip file

What it means

MultiDexFileReader.open(byte[]) throws IOException as a final fallback when the input's first bytes match neither the 'dex' magic nor the 'PK' zip prefix, i.e. the byte array is not a dex file and not a zip container. The library auto-detects format from the magic bytes and has no handler for anything else.

Solutions

  1. Check the first bytes of your input (file/x magic) to confirm it is a dex or zip.
  2. If the content is gzip/other-compressed, decompress before calling open().
  3. If you got HTML/JSON from a failed HTTP download, fix the download (check URL, status code) and retry.
  4. For .odex/.vdex or native binaries, convert/deoptimize them to a real dex first.

Example fix

// before
BaseDexFileReader r = MultiDexFileReader.open(bytes);
// after
String magic = new String(bytes, 0, 3, StandardCharsets.ISO_8859_1);
if (!magic.startsWith("dex") && !magic.startsWith("PK")) {
    throw new IllegalArgumentException("expected dex or zip, got magic=" + magic);
}
BaseDexFileReader r = MultiDexFileReader.open(bytes);
Defensive patterns

Strategy: validation

Validate before calling

String magic = data.length >= 3 ? new String(data, 0, 3, StandardCharsets.ISO_8859_1) : "";
if (!magic.startsWith("dex") && !magic.startsWith("PK")) {
    throw new IllegalArgumentException("expected dex or zip, got magic=" + magic);
}

Type guard

static boolean isDexOrZip(byte[] d) {
    return d != null && d.length >= 3 &&
        (new String(d, 0, 3, StandardCharsets.ISO_8859_1).startsWith("dex") ||
         new String(d, 0, 2, StandardCharsets.ISO_8859_1).equals("PK"));
}

Try / catch

try {
    BaseDexFileReader r = MultiDexFileReader.open(bytes);
} catch (IOException e) {
    LOG.error("unsupported format: " + e.getMessage());
}

Prevention

When it happens

Trigger: Calling MultiDexFileReader.open(bytes) on content starting with anything other than 'dex' or 'PK' — e.g. an ELF .so library, a binary XML/ARSB file, a gzip stream, or plain text/HTML from a failed download.

Common situations: Downloading an APK via a URL that returned an HTML error page; passing an .odex/.vdex or native library where classes.dex was intended; passing a gzip-compressed dex that was never gunzipped.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

Thrown at dex-reader/src/main/java/com/googlecode/d2j/reader/MultiDexFileReader.java:58

            try (ZipFile zipFile = new ZipFile(data)) {
                for (ZipEntry e : zipFile.entries()) {
                    String entryName = e.getName();
                    if (entryName.startsWith("classes") && entryName.endsWith(".dex")) {
                        if (!dexFileReaders.containsKey(entryName)) { // only the first one
                            dexFileReaders.put(entryName, new DexFileReader(toByteArray(zipFile.getInputStream(e))));
                        }
                    }
                }
            }
            if (dexFileReaders.size() == 0) {
                throw new IOException("Can not find classes.dex in zip file");
            } else if (dexFileReaders.size() == 1) {
                return dexFileReaders.firstEntry().getValue();
            } else {
                return new MultiDexFileReader(dexFileReaders.values());
            }
        }
        throw new IOException("The source file is not a .dex or .zip file");
    }

    void init() {
        Set<String> classes = new HashSet<>();
        for (DexFileReader reader : readers) {
            List<String> classNames = reader.getClassNames();
            for (int i = 0; i < classNames.size(); i++) {
                String className = classNames.get(i);
                if (classes.add(className)) {
                    items.add(new Item(i, reader, className));
                }
            }
        }
    }

    @Override
    public int getDexVersion() {
        int max = DexConstants.DEX_035;

View on GitHub (pinned to b5bda4fb49)