iBotPeaches/Apktool · error · BrutException

could not exec:

Error message

could not exec: 

What it means

Thrown by OS.exec when ProcessBuilder.start() raises IOException — the process was never created. Typical causes: the executable does not exist (message often 'Cannot run program ... No such file or directory'), is not executable, or the OS refused the spawn (fork limit, permission denied). The failed command array is included in the message and the IOException is the cause.

Source

Thrown at brut.j.util/src/main/java/brut/util/OS.java:150

                cpfile(file, destFile);
            }
        }
    }

    public static void exec(String[] cmd) throws BrutException {
        try {
            ProcessBuilder builder = new ProcessBuilder(cmd);
            Process ps = builder.start();

            new StreamForwarder(ps.getErrorStream(), "ERROR").start();
            new StreamForwarder(ps.getInputStream(), "OUTPUT").start();

            int exitValue = ps.waitFor();
            if (exitValue != 0) {
                throw new BrutException("Execution failed (exit code = " + exitValue + "): " + Arrays.toString(cmd));
            }
        } catch (IOException ex) {
            throw new BrutException("could not exec: " + Arrays.toString(cmd), ex);
        } catch (InterruptedException ex) {
            throw new BrutException("could not exec : " + Arrays.toString(cmd), ex);
        }
    }

    public static String execAndReturn(String[] cmd) {
        ExecutorService executor = Executors.newCachedThreadPool();
        try {
            ProcessBuilder builder = new ProcessBuilder(cmd);
            builder.redirectErrorStream(true);

            Process process = builder.start();
            StreamCollector collector = new StreamCollector(process.getInputStream());
            executor.execute(collector);
            process.waitFor(15, TimeUnit.SECONDS);
            executor.shutdownNow();

            if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {

View on GitHub (pinned to 79b63384d7)

Solutions

  1. Verify the executable resolves and is runnable before exec: new File(cmd[0]).canExecute() or 'which <bin>'
  2. chmod +x the extracted binary after pulling it out of the jar (Jar extraction does not preserve the exec bit)
  3. Use an absolute path to the binary instead of relying on PATH, and confirm no unquoted spaces in each argv element
  4. On 64-bit-only systems, install 32-bit compatibility libs or point to a 64-bit build of the tool

Example fix

// before
OS.exec(new String[]{"/tmp/BRUT123/aapt", "v"}); // IOException: cannot run program

// after
File bin = new File("/tmp/BRUT123/aapt");
if (!bin.canExecute() && !bin.setExecutable(true)) {
    throw new BrutException("Cannot make executable: " + bin);
}
OS.exec(new String[]{bin.getAbsolutePath(), "v"});
Defensive patterns

Strategy: validation

Validate before calling

void ensureExecutable(String binPath) throws IOException {
    File bin = new File(binPath);
    if (!bin.isFile()) throw new FileNotFoundException(binPath);
    if (!bin.canExecute() && !bin.setExecutable(true)) {
        throw new IOException("cannot mark executable: " + binPath);
    }
}
// ensureExecutable(cmd[0]); OS.exec(cmd);

Try / catch

try {
    OS.exec(cmd);
} catch (BrutException e) {
    if (e.getCause() instanceof IOException
            && e.getCause().getMessage().contains("No such file")) {
        // binary missing: fix PATH or extraction, not retryable
        throw new EnvironmentException("tool not found: " + cmd[0], e);
    }
    throw e;
}

Prevention

When it happens

Trigger: OS.exec(cmd) where cmd[0] names a binary not on PATH or at a wrong absolute path, the file lacks the execute bit, or it is a directory; also spawn failures such as EMFILE/ENOMEM under heavy load.

Common situations: Extracted native helper (aapt and friends) not marked +x or extracted to a path containing spaces that was not quoted in argv; PATH differs in CI/containers versus local shell; 32-bit binary on a 64-bit-only image; running on a JRE without the required exec permission in sandboxed environments.

Related errors


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