Hmbown/CodeWhale · error

Android loaded image

Error message

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

What it means

After both path authorities agree and the path is not the linker, the updater stats the resolved file to confirm it is an executable regular file before selecting it as the update target. If it is missing, a directory, a symlink to nothing, or lacks the execute bit, the updater refuses — replacing such a path would not yield a runnable updated binary.

Solutions

  1. Re-install the binary freshly so a live executable file exists at the path, then re-run the update.
  2. Restore the execute bit: `chmod 755 <path-to-binary>`, then retry.
  3. Verify with `ls -l` and `stat` that the resolved path from the error message exists, is a regular file, and is executable.
  4. If the binary was replaced underneath the running process, kill the old process and start the newly installed binary by its full path before updating again.

Example fix

// before
cp codewhale $PREFIX/bin/ && $PREFIX/bin/codewhale update   # exec bit lost
// after
install -m 755 codewhale $PREFIX/bin/codewhale && $PREFIX/bin/codewhale update
Defensive patterns

Strategy: validation

Validate before calling

use std::os::unix::fs::PermissionsExt;
fn is_executable_file(p: &std::path::Path) -> bool {
    std::fs::metadata(p)
        .map(|m| m.is_file() && m.permissions().mode() & 0o111 != 0)
        .unwrap_or(false)
}
if !is_executable_file(&target) { /* reinstall or chmod before updating */ }

Try / catch

match run_update() {
    Err(e) if e.to_string().contains("not an executable regular file") => {
        // prompt: reinstall the release, then retry
    }
    other => other?,
}

Prevention

When it happens

Trigger: android_loaded_executable_proof when is_executable_file() returns false for the resolved mapping path (file deleted after mapping, permissions stripped, path now points at a non-regular file).

Common situations: The binary was deleted or replaced on disk while the process still ran (maps refers to the unlinked inode path); a package manager or cleaner app removed the app's native lib/binary; the executable bit was lost after copying the binary manually (common when extracting from an archive on Android).

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/17eb099e5ad1ff51. Report an issue: GitHub.

Appendix: source

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

            "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 73e0f67d83)