Hmbown/CodeWhale · error · anyhow::Error

Android loaded image `{}` is not an executable regular file;

Error message

Android loaded image `{}` is not an executable regular file; refusing to select an update target

What it means

After both Android authorities agreed on a canonical path, is_executable_file found it is not an executable regular file (missing any execute bit or not a regular file). The updater refuses to select such a target because writing an update there could clobber something that is not the running program.

Source

Thrown at crates/cli/src/update.rs:430

            "failed to canonicalize Android loaded-image mapping {}",
            mapping.path.display()
        )
    })?;
    if resolved_dladdr != resolved_mapping {
        bail!(
            "Android loaded-image authorities disagree: dladdr resolved to {}, but /proc/self/maps resolved to {}",
            resolved_dladdr.display(),
            resolved_mapping.display()
        );
    }
    if is_android_linker_name(&resolved_mapping) {
        bail!(
            "Android loaded-image authorities resolved to runtime linker {}; refusing to use the linker as an update target",
            resolved_mapping.display()
        );
    }
    if !is_executable_file(&resolved_mapping) {
        bail!(
            "Android loaded image `{}` is not an executable regular file; refusing to select an update target",
            resolved_mapping.display()
        );
    }

    validate_android_mapping_identity(&mapping, &resolved_mapping)?;
    Ok(AndroidExecutableProof {
        path: resolved_mapping,
        device_major: mapping.device_major,
        device_minor: mapping.device_minor,
        inode: mapping.inode,
        proof_kind: AndroidExecutableProofKind::DladdrAndProcMaps,
    })
}

#[cfg(any(target_os = "android", all(test, unix)))]
fn validate_android_reported_path(authority: &str, path: &Path) -> Result<()> {
    if !path.is_absolute() {

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Restore the execute bit: chmod +x <path-from-message>
  2. Reinstall the binary using the documented installer so modes are set correctly
  3. Confirm the path is a regular file (ls -l) and not a directory or special file

Example fix

// before
$ ls -l /data/local/tmp/codewhale
-rw-r--r-- 1 user user 12345 codewhale
codewhale update  # -> Android loaded image ... is not an executable regular file

// after
$ chmod +x /data/local/tmp/codewhale
codewhale update  # proceeds
Defensive patterns

Strategy: validation

Validate before calling

use std::os::unix::fs::PermissionsExt;

fn image_is_executable_regular_file(path: &std::path::Path) -> bool {
    std::fs::metadata(path)
        .map(|m| m.is_file() && m.permissions().mode() & 0o111 != 0)
        .unwrap_or(false)
}

// run before self-update:
if !image_is_executable_regular_file(&std::env::current_exe().unwrap()) {
    eprintln!("binary lost its execute bit; fix with chmod +x before updating");
}

Try / catch

Catch the error and, because the resolved path is included in the message, offer to run chmod +x on that exact path, then retry the update once.

Prevention

When it happens

Trigger: Android self-update where the resolved image path lost its execute bit or is no longer a regular file - e.g. the binary was copied via unzip/MTP without preserving modes, chmod -x was applied, or the path now points at a symlink target/special file.

Common situations: Binaries extracted from archives without permission preservation, sideloaded copies, permission resets by sync tools.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/17eb099e5ad1ff51. Report an issue: GitHub.