iBotPeaches/Apktool · error · AndrolibException

Could not set aapt binary as executable:

Error message

Could not set aapt binary as executable: 

What it means

AndrolibException from AaptManager.setBinaryExecutable() when File.setExecutable(true) returns false — the extracted aapt2 binary could not be marked executable. On POSIX systems this happens with noexec-mounted filesystems or missing ownership; on Windows it indicates ACL problems. Without the executable bit aapt2 cannot be spawned, so resource packing fails before it starts.

Source

Thrown at brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AaptManager.java:75

            binPath.append(".exe");
        }

        File binFile;
        try {
            binFile = Jar.getResourceAsFile(AaptManager.class, binPath.toString(), binName + "_");
        } catch (BrutException ex) {
            throw new AndrolibException(ex);
        }
        setBinaryExecutable(binFile);
        return binFile;
    }

    private static void setBinaryExecutable(File binFile) throws AndrolibException {
        if (!binFile.isFile() || !binFile.canRead()) {
            throw new AndrolibException("Could not read aapt binary: " + binFile.getPath());
        }
        if (!binFile.setExecutable(true)) {
            throw new AndrolibException("Could not set aapt binary as executable: " + binFile.getPath());
        }
    }

    public static int getBinaryVersion(File binFile) throws AndrolibException {
        setBinaryExecutable(binFile);

        String versionStr = OS.execAndReturn(new String[] { binFile.getPath(), "version" });
        if (versionStr == null) {
            throw new AndrolibException("Could not execute aapt binary at location: " + binFile.getPath());
        }

        return getVersionFromString(versionStr);
    }

    public static int getVersionFromString(String versionStr) throws AndrolibException {
        if (versionStr.startsWith("Android Asset Packaging Tool (aapt) 2:")) {
            return 2;
        }

View on GitHub (pinned to 79b63384d7)

Solutions

  1. Point temp extraction at an exec-allowed directory: mkdir -p /var/tmp/apktool && apktool b app --temp-path /var/tmp/apktool.
  2. Remount the tmp filesystem without noexec, or set TMPDIR to such a location.
  3. Supply your own aapt2 via --aapt pointing at a binary you can execute (e.g. from Android SDK build-tools).

Example fix

# before (TMPDIR on noexec fs)
apktool b app
# after
mkdir -p /var/tmp/apktool
apktool b app --temp-path /var/tmp/apktool
# alternatively
apktool b app --aapt $ANDROID_HOME/build-tools/34.0.0/aapt2
Defensive patterns

Strategy: validation

Validate before calling

// Ensure temp dir is on an exec-mounted filesystem
String[] mount = OS.execAndReturn(new String[]{"findmnt", "-T", System.getProperty("java.io.tmpdir"), "-o", "OPTIONS"}).split("\\s+");
if (Arrays.stream(mount).anyMatch(o -> o.contains("noexec"))) {
    config.setTempDirectory("/var/tmp/apktool");
}

Prevention

When it happens

Trigger: TMPDIR or the extraction dir on a filesystem mounted noexec; running as a user without chmod rights on the extracted file (unusual ACL/NFS setups); Windows directories with restrictive ACLs.

Common situations: Hardened CI runners that mount /tmp noexec; containers with read-only or noexec tmpfs; NFS-mounted homes with root_squash breaking chmod.

Related errors


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