MuntashirAkon/AppManager · error · DexFileFactory.UnsupportedFileTypeException

InputStream is not a dex, odex file.

Error message

InputStream is not a dex, odex file.

What it means

DexUtils.loadDexContainer() sniffs the input stream by attempting DexBackedDexFile and then DexBackedOdexFile parsing; when both reject the data it throws DexFileFactory.UnsupportedFileTypeException with this message. It means the stream is neither a standard DEX nor an ODEX file, so no dex container can be produced from it.

Source

Thrown at app/src/main/java/io/github/muntashirakon/AppManager/dex/DexUtils.java:229

            javaClass.decompile();
            return javaClass.getCode();
        }
    }

    @NonNull
    public static DexBackedDexFile loadDexContainer(@NonNull InputStream inputStream, int api) throws IOException {
        Opcodes opcodes = api < 0 ? Opcodes.getDefault() : Opcodes.forApi(api);
        try {
            return DexBackedDexFile.fromInputStream(opcodes, inputStream);
        } catch (DexBackedDexFile.NotADexFile ex) {
            // just eat it
        }
        try {
            return DexBackedOdexFile.fromInputStream(opcodes, inputStream);
        } catch (DexBackedOdexFile.NotAnOdexFile ex) {
            // just eat it
        }
        throw new DexFileFactory.UnsupportedFileTypeException("InputStream is not a dex, odex file.");
    }
}

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Verify the stream starts with the DEX magic bytes 0x64 0x65 0x78 0x0A ("dex\n") or ODEX magic "dey\n" before calling loadDexContainer
  2. If the input is an APK/JAR/ZIP, extract the classes*.dex entries first and feed those streams
  3. If the input is VDEX/CDex (newer ART formats), convert it back to dex with external tools — this library does not parse them
  4. Re-obtain the file and check its integrity (size/hash) in case of truncation or corruption

Example fix

// before
DexContainer container = DexUtils.loadDexContainer(stream, opcodes);
// after
byte[] header = new byte[4];
try (DataInputStream in = new DataInputStream(stream)) {
    in.readFully(header);
    if (!(new String(header, "ISO_8859_1").startsWith("dex\n"))) {
        throw new IllegalArgumentException("Not a DEX file (bad magic)");
    }
}
DexContainer container = DexUtils.loadDexContainer(new ByteArrayInputStream(header), opcodes);
Defensive patterns

Strategy: try-catch

Validate before calling

byte[] magic = new byte[4]; int n = stream.read(magic); if (n < 4 || !(new String(magic, 0, 4, StandardCharsets.ISO_8859_1).startsWith("dex\n") || new String(magic, 0, 4, StandardCharsets.ISO_8859_1).startsWith("dey\n"))) throw new IllegalArgumentException("Not a dex/odex stream");

Type guard

boolean looksLikeDex(byte[] b) { return b != null && b.length > 7 && b[0]=='d' && b[1]=='e' && b[2]=='x' && b[3]=='\n'; }

Try / catch

try { DexContainer c = DexUtils.loadDexContainer(stream, opcodes); } catch (DexFileFactory.UnsupportedFileTypeException e) { /* fall back to zip extraction of classes*.dex or inform user the file is unsupported */ }

Prevention

When it happens

Trigger: Passing an InputStream to DexUtils.loadDexContainer() whose bytes are not DEX (magic "dex\n") or ODEX (magic "dey\n") — e.g. a ZIP/APK, a VDEX/CDex artifact, a text file, or a truncated/corrupted dex.

Common situations: Extracting the wrong entry from an APK (resources.arsc instead of classes.dex); passing a .vdex file from newer Android art; passing the APK itself instead of the inner dex; downloading a dex that was truncated or HTML-error-paged.

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 MuntashirAkon/AppManager@0152f468fc (2026-09-12). Data as JSON: /api/errors/284821497bfa3a71. Report an issue: GitHub.