unicity-aos/aos-ce · error · std::io::Error

bundled executable is not executable at

Error message

bundled {label} executable is not executable at {}

What it means

This io::Error (PermissionDenied) is thrown by ensure_runtime_executable in crates/unicity-aos-bootstrap/src/lib.rs when a bundled executable exists as a regular file but its Unix permission bits grant no execute access to anyone (mode & 0o111 == 0). The library checks the binary before spawning it so a confusing exec failure never happens later; here the file was found but is not runnable as-is.

Solutions

  1. Restore the execute bit: chmod +x <path shown in the error message> and retry.
  2. Re-extract or reinstall the bundled artifact in a way that preserves the executable permission (tar -xpf, correct umask).
  3. If packaging the binary yourself, set mode 0755 (or at least 0o111 bits) on the file in the build/install step.
  4. Verify with 'ls -l <path>' that at least one execute bit (u/g/o) is set before re-running.

Example fix

// before (shell): archive extraction lost the exec bit
tar -xzf aos-bundle.tar.gz -C /opt/aos
// after
chmod +x /opt/aos/bin/runtime && tar -xzf aos-bundle.tar.gz -C /opt/aos  # or chmod after extraction
Defensive patterns

Strategy: validation

Validate before calling

use std::os::unix::fs::PermissionsExt;
let md = std::fs::metadata(&binary)?;
if !md.is_file() || md.permissions().mode() & 0o111 == 0 {
    return Err(format!("{} is missing the execute bit; run: chmod +x {}", binary.display(), binary.display()));
}

Try / catch

match std::fs::metadata(&binary) {
    Ok(md) if md.is_file() && md.permissions().mode() & 0o111 != 0 => { /* proceed */ }
    _ => eprintln!("bundled runtime missing or not executable; run `chmod +x <path>` or reinstall"),
}

Prevention

When it happens

Trigger: Calling foreground_daemon_command or ensure_runtime_available (or run/spawn variants that call ensure_runtime_executable) when the binary at the resolved runtime path exists and is a file, but has permission bits like 0644/0600 — i.e. no x bit for user, group, or other.

Common situations: The bundled binary was extracted from an archive (tar/zip) that lost the execute bit; a package or container build copied the file without preserving permissions; a post-install chmod step was skipped; the file was written programmatically with default non-executable permissions.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13). Data as JSON: /api/errors/f97f91cf905aad3f. Report an issue: GitHub.

Appendix: source

Thrown at crates/unicity-aos-bootstrap/src/lib.rs:544

                )
            } else {
                error
            }
        })?;
        if !metadata.is_file() {
            return Err(io::Error::new(
                io::ErrorKind::NotFound,
                format!(
                    "bundled {label} executable not found at {}",
                    binary.display()
                ),
            ));
        }
        #[cfg(unix)]
        {
            use std::os::unix::fs::PermissionsExt;
            if metadata.permissions().mode() & 0o111 == 0 {
                return Err(io::Error::new(
                    io::ErrorKind::PermissionDenied,
                    format!(
                        "bundled {label} executable is not executable at {}",
                        binary.display()
                    ),
                ));
            }
        }
        Ok(())
    }
}

fn create_private_dir(path: &Path) -> io::Result<()> {
    fs::create_dir_all(path)?;
    let metadata = fs::symlink_metadata(path)?;
    if metadata.file_type().is_symlink() || !metadata.is_dir() {
        return Err(io::Error::new(
            io::ErrorKind::InvalidInput,

View on GitHub (pinned to f6f22024fb)