iBotPeaches/Apktool · error · AndrolibException

Could not open apk file: {apkFile}

Error message

Could not open apk file: {apkFile}

What it means

SmaliDecoder's constructor eagerly initializes the lazily-initialized, non-thread-safe ZipDexContainer by calling getEntry("") on the constructing thread. If that probe throws an IOException, the APK cannot be opened as a dex-bearing ZIP and this AndrolibException is thrown with the file name.

Source

Thrown at brut.apktool/apktool-lib/src/main/java/brut/androlib/smali/SmaliDecoder.java:48

import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

public class SmaliDecoder {
    private final ZipDexContainer mDexContainer;
    private final boolean mDebugMode;
    private final Set<String> mDexFiles;
    private final AtomicInteger mInferredApiLevel;

    public SmaliDecoder(File apkFile, boolean debugMode) throws AndrolibException {
        mDexContainer = new ZipDexContainer(apkFile, null);
        // ZipDexContainer is lazily initialized and not thread-safe. Eagerly initialize on the constructing thread.
        try {
            mDexContainer.getEntry("");
        } catch (IOException ex) {
            throw new AndrolibException("Could not open apk file: " + apkFile, ex);
        }
        mDebugMode = debugMode;
        mDexFiles = ConcurrentHashMap.newKeySet();
        mInferredApiLevel = new AtomicInteger();
    }

    public Set<String> getDexFiles() {
        return mDexFiles;
    }

    public int getInferredApiLevel() {
        return mInferredApiLevel.get();
    }

    public void decode(String dexName, File outDir) throws AndrolibException {
        try {
            // Fetch the requested dex file from the dex container.
            ZipDexContainer.DexEntry<DexBackedDexFile> dexEntry = mDexContainer.getEntry(dexName);

View on GitHub (pinned to 79b63384d7)

Solutions

  1. Validate the container first: `unzip -l app.apk` must list classes.dex entries
  2. If the file is a bundle format, extract the real APK first and pass that
  3. Check read permissions and re-obtain the file if the download was truncated (compare size/CRC)
  4. Catch AndrolibException at construction and surface the file name to the user instead of decoding

Example fix

// before
SmaliDecoder decoder = new SmaliDecoder(new File("app.xapk"), false);

// after
File apk = new File("base.apk");
try (ZipFile z = new ZipFile(apk)) {
    if (z.stream().noneMatch(e -> e.getName().endsWith(".dex"))) {
        throw new IllegalArgumentException("No dex entries in " + apk);
    }
}
SmaliDecoder decoder = new SmaliDecoder(apk, false);
Defensive patterns

Strategy: validation

Validate before calling

File apk = new File(path);
try (ZipFile zf = new ZipFile(apk)) {
    boolean hasDex = zf.stream().anyMatch(e -> e.getName().endsWith(".dex"));
    if (!hasDex) throw new IllegalArgumentException("No dex entries in " + apk);
} catch (IOException e) {
    throw new IllegalArgumentException("Not a readable ZIP/APK: " + apk, e);
}

Try / catch

try {
    SmaliDecoder decoder = new SmaliDecoder(apkFile, debugMode);
} catch (AndrolibException e) {
    // constructor failure == file-level problem; do not retry with the same file
    throw new IllegalArgumentException("Cannot open APK for smali decode: " + apkFile, e);
}

Prevention

When it happens

Trigger: Constructing SmaliDecoder with a file that is not a ZIP, is corrupt, lacks dex entries, or cannot be read. The eager init exists to force all ZIP parsing onto one thread, so any structural ZIP problem surfaces here rather than later during parallel decode.

Common situations: Decoding a file that is actually an XAPK/APKM bundle, a partially downloaded APK, an encrypted APK, or a path with wrong permissions — typically in programs driving apktool-lib programmatically.

Related errors


AI-assisted analysis of iBotPeaches/Apktool@79b63384d7 (2026-08-14). Data as JSON: /api/errors/9014e2e006e25aae. Report an issue: GitHub.