{"record":{"id":"44c9b65273b391ea","repo":"Hmbown/CodeWhale","slug":"multiple-proc-self-maps-rows-contain-the-updater","errorCode":null,"errorMessage":"multiple /proc/self/maps rows contain the updater marker","messagePattern":"multiple /proc/self/maps rows contain the updater marker","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/cli/src/update.rs","lineNumber":410,"sourceCode":"            .context(\"loaded-image mapping has an invalid device\")?;\n        let device_major = u32::from_str_radix(device_major, 16)\n            .context(\"loaded-image mapping has an invalid device major number\")?;\n        let device_minor = u32::from_str_radix(device_minor, 16)\n            .context(\"loaded-image mapping has an invalid device minor number\")?;\n        if path.is_empty() {\n            bail!(\"loaded-image mapping for updater marker has no pathname\");\n        }\n\n        let mapping = AndroidImageMapping {\n            start,\n            end,\n            device_major,\n            device_minor,\n            inode,\n            path: PathBuf::from(path),\n        };\n        if matching.replace(mapping).is_some() {\n            bail!(\"multiple /proc/self/maps rows contain the updater marker\");\n        }\n    }\n\n    matching.ok_or_else(|| anyhow!(\"no /proc/self/maps row contains the updater marker\"))\n}\n\n#[cfg(all(test, unix))]\nfn resolve_android_loaded_executable_report(\n    maps: &str,\n    marker: u64,\n    dladdr_path: &Path,\n) -> Result<PathBuf> {\n    Ok(android_loaded_executable_proof_report(maps, marker, dladdr_path)?.path)\n}\n\n#[cfg(any(target_os = \"android\", all(test, unix)))]\nfn android_loaded_executable_proof_report(\n    maps: &str,","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/cli/src/update.rs#L392-L428","documentation":"During a self-update on Android, the updater locates its own loaded executable image by finding the /proc/self/maps row that contains the address of a function inside the updater (the marker address). parse_android_image_mapping scans the maps text and keeps at most one matching executable row; if more than one maps row spans the marker address it refuses to guess and throws this error. It is a deliberate ambiguity guard so the updater never replaces the wrong file.","triggerScenarios":"Calling the Android self-update path when /proc/self/maps contains two or more rows whose [start,end) address range contains the updater's marker address (e.g. duplicated or overlapping mappings of the binary).","commonSituations":"Kernel/linker producing overlapping executable mappings of the same image (e.g. unusual hugepage or shared mapping setups), custom or modified map entries, or running under emulation/sandboxes that split the text segment into multiple maps rows.","solutions":["Inspect `cat /proc/self/maps` in the failing environment and identify why more than one executable row spans the updater's address; fix the duplication at the container/emulation level.","Retry the update by running the installed binary directly from a normal filesystem path (e.g. /data/app/... or $PREFIX/bin) instead of under the unusual environment.","Report the environment details (Android version, linker, sandbox) upstream; the parser could be taught to disambiguate rows with identical device/inode/path.","As a workaround, replace the binary manually (download the new release and copy it over the installed path) rather than using in-place self-update."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"fn maps_rows_for_marker(maps: &str, marker: u64) -> usize {\n    maps.lines().filter(|l| {\n        l.split_whitespace().next()\n            .and_then(|r| r.split_once('-'))\n            .and_then(|(s, e)| Some(u64::from_str_radix(s,16).ok()? <= marker && marker < u64::from_str_radix(e,16).ok()?))\n            .unwrap_or(false)\n    }).count()\n}\n// call before update; if > 1, do not attempt in-place self-update","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Inspect /proc/self/maps in your target environment before shipping self-update there.","Run updates from a normally loaded binary on a standard filesystem.","Avoid sandboxes/emulators that split executable mappings.","Prefer manual replacement over in-place self-update in exotic environments."],"tags":["android","self-update","procfs","ambiguity"],"backgroundTag":"unexpected-response-shape","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}