Hmbown/CodeWhale · error
Android reported deleted loaded image
Error message
Android {authority} reported deleted loaded image `{}` What it means
Linux appends " (deleted)" to the path in /proc/self/maps when the mapped file has been unlinked. A deleted loaded image means the on-disk file the process runs from no longer exists at that name, so there is nothing legitimate to replace — updating would target a name no longer backed by the running inode. The updater detects the suffix and refuses.
Solutions
- Kill the running process and start the newly installed binary by its full path; self-update only from a binary that still exists on disk.
- Reinstall the current release so a live file exists at the expected path, then run the update from that fresh process.
- Avoid deleting/renaming the updater binary while an update from it is in flight.
- If this recurs after every update, check for another agent (sync client, antivirus, package manager) removing the binary mid-run.
Defensive patterns
Strategy: validation
Validate before calling
fn path_is_live(p: &std::path::Path) -> bool {
let s = p.to_string_lossy();
!s.ends_with(" (deleted)") && p.exists()
}
if !path_is_live(&reported_path) { /* restart from a freshly installed binary before updating */ } Try / catch
match run_update() {
Err(e) if e.to_string().contains("reported deleted loaded image") => {
// instruct user: restart the newly installed binary by full path, retry
}
other => other?,
} Prevention
- Never rm/rename the binary while a process is running from it.
- After replacing a binary, always start the new one before updating again.
- Check for background agents (sync, AV, package manager) touching the install directory.
- Make updates atomic and serialized within your own tooling.
When it happens
Trigger: validate_android_reported_path, called from android_loaded_executable_proof_report, when either the dladdr path or the maps row path ends with " (deleted)".
Common situations: Something replaced or deleted the binary while the old process was still running (e.g. a prior partial update, an `rm` + reinstall, or a package manager swap); the updater itself previously swapped files without restarting the process.
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
- Android loaded-image authorities disagree: dladdr resolved…
- multiple /proc/self/maps rows contain the updater marker
- Android identifies runtime linker ` `; refusing to use the…
- Android reported non-absolute loaded-image path
- Android dladdr could not locate the updater's loaded image
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/24522ec3e0758fc4.
Report an issue: GitHub.
Appendix: source
Thrown at crates/cli/src/update.rs:487
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() {
bail!(
"Android {authority} reported non-absolute loaded-image path `{}`",
path.display()
);
}
if path.to_string_lossy().ends_with(" (deleted)") {
bail!(
"Android {authority} reported deleted loaded image `{}`",
path.display()
);
}
if is_android_linker_name(path) {
bail!(
"Android {authority} identifies runtime linker `{}`; refusing to use the linker as an update target",
path.display()
);
}
Ok(())
}
#[cfg(any(target_os = "android", all(test, unix)))]
fn validate_android_mapping_identity(
mapping: &AndroidImageMapping,
candidate: &Path,
) -> Result<()> {View on GitHub (pinned to 73e0f67d83)