iBotPeaches/Apktool · error · AndrolibException
Cannot disassemble an odex file without deodexing it: {dexNa
Error message
Cannot disassemble an odex file without deodexing it: {dexName} What it means
During baksmali decoding, a dex file in the container reports supportsOptimizedOpcodes(), i.e. it is an optimized dex (odex/oat artifact from a device's dalvik-art cache), not plain dex. Baksmali cannot disassemble optimized opcodes without a deodexing context, so apktool refuses.
Source
Thrown at brut.apktool/apktool-lib/src/main/java/brut/androlib/smali/SmaliDecoder.java:103
int dexNum;
try {
dexNum = Integer.parseInt(dexEntryName.substring(prefix.length()));
} catch (NumberFormatException ignored) {
continue;
}
if (dexNum > 1) {
dexFiles.put(dexNum, mDexContainer.getEntry(dexEntryName).getDexFile());
}
}
// Decode the dex files into separate folders.
for (Map.Entry<Integer, DexBackedDexFile> entry : dexFiles.entrySet()) {
int dexNum = entry.getKey();
DexBackedDexFile dexFile = entry.getValue();
if (dexFile.supportsOptimizedOpcodes()) {
throw new AndrolibException("Cannot disassemble an odex file without deodexing it: " + dexName);
}
String dirName = "smali";
if (dexNum > 1 || !dexName.equals("classes.dex")) {
dirName += "_" + dexName.substring(0, dexName.lastIndexOf('.')).replace('/', '@');
if (dexNum > 1) {
dirName += dexNum;
}
}
decodeFile(dexFile, new File(outDir, dirName));
}
mDexFiles.add(dexName);
} catch (IOException ex) {
throw new AndrolibException("Could not baksmali file: " + dexName, ex);
}
}View on GitHub (pinned to 79b63384d7)
Solutions
- Decode the original APK (base.apk from the device/Play store) rather than dalvik-cache artifacts
- For real odex files, deodex first using baksmali with a matching boot.oat/boot.art (`baksmali deodex -b boot.oat file.odex`), then work with the plain dex
- Ensure the odex's boot image comes from the exact same ROM build as the odex, otherwise deodex fails
- Alternatively skip the odex entry: decode only known plain-dex entries by name
Example fix
# before # pulled /data/dalvik-cache/arm64/data@app@@com.example*==/base.apk@classes.dex apktool d cached.apk # Cannot disassemble an odex file without deodexing it # after # get the original, non-optimized artifact and deodex properly baksmali deodex -b boot.oat app.odex -o out apktool d original-base.apk
Defensive patterns
Strategy: validation
Validate before calling
// Detect optimized dex before decode
// DexBackedDexFile.supportsOptimizedOpcodes() is the check apktool uses;
// from outside, screen inputs by origin: reject files pulled from dalvik-cache
if (path.contains("dalvik-cache") || path.endsWith(".odex")) {
throw new IllegalArgumentException("Optimized dex requires deodexing first: " + path);
} Try / catch
try {
decoder.decode(dexName, outDir);
} catch (AndrolibException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Cannot disassemble an odex")) {
// deodex with matching boot.oat via baksmali, or decode the original APK instead
} else { throw e; }
} Prevention
- Decode original APKs from the store/device, never dalvik-cache artifacts
- For odex workflows, always fetch boot.oat from the same ROM build
- Screen input files by extension and origin before invoking the decoder
When it happens
Trigger: Calling SmaliDecoder.decode on an APK or container that contains an odex entry (e.g. classes pulled from /data/dalvik-cache, or an .odex file), where the dex uses quickened/optimized opcodes.
Common situations: Pulling optimized dex from a rooted device's ART cache instead of the original APK; handling OEM .odex files; trying to decode with a tool version whose deodex path is not enabled.
Related errors
- Could not smali folder: {smaliDir.getName()}
- Could not open apk file: {apkFile}
- Could not find file: {dexName}
- Could not baksmali file: {dexName}
- Legacy aapt is no longer supported.
AI-assisted analysis of iBotPeaches/Apktool@79b63384d7 (2026-08-14).
Data as JSON: /api/errors/783c714edc0c6f2d.
Report an issue: GitHub.