{"record":{"id":"980f29fbe72e7540","repo":"Hmbown/CodeWhale","slug":"android-authority-identifies-runtime-linker","errorCode":null,"errorMessage":"Android {authority} identifies runtime linker `{}`; refusing to use the linker as an update target","messagePattern":"Android (.+?) identifies runtime linker `(.+?)`; refusing to use the linker as an update target","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/cli/src/update.rs","lineNumber":461,"sourceCode":"    })\n}\n\n#[cfg(any(target_os = \"android\", all(test, unix)))]\nfn validate_android_reported_path(authority: &str, path: &Path) -> Result<()> {\n    if !path.is_absolute() {\n        bail!(\n            \"Android {authority} reported non-absolute loaded-image path `{}`\",\n            path.display()\n        );\n    }\n    if path.to_string_lossy().ends_with(\" (deleted)\") {\n        bail!(\n            \"Android {authority} reported deleted loaded image `{}`\",\n            path.display()\n        );\n    }\n    if is_android_linker_name(path) {\n        bail!(\n            \"Android {authority} identifies runtime linker `{}`; refusing to use the linker as an update target\",\n            path.display()\n        );\n    }\n    Ok(())\n}\n\n#[cfg(any(target_os = \"android\", all(test, unix)))]\nfn validate_android_mapping_identity(\n    mapping: &AndroidImageMapping,\n    candidate: &Path,\n) -> Result<()> {\n    use std::os::unix::fs::MetadataExt;\n\n    let candidate_metadata = std::fs::metadata(candidate).with_context(|| {\n        format!(\n            \"failed to stat Android update target {}\",\n            candidate.display()","sourceCodeStart":443,"sourceCodeEnd":479,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/cli/src/update.rs#L443-L479","documentation":"validate_android_reported_path (applied to each authority separately: dladdr or /proc/self/maps) found the reported path names Bionic's runtime linker. Updating would overwrite a system component, so the check refuses; this is the per-authority form of the linker guard that also exists after the two authorities are joined.","triggerScenarios":"Android self-update where one authority's raw path already matches is_android_linker_name (e.g. /system/bin/linker64, /apex/com.android.art/bin/linker64, ld-android.so) before canonicalization and comparison.","commonSituations":"Same class as the post-join linker refusal: dlopen-based launchers, mispackaged builds, linker-namespace quirks on specific Android versions.","solutions":["Launch the binary directly (exec) instead of loading it through the linker or a wrapper","Reinstall using the documented Android method and retry","Report the authority name and path from the message for triage"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"Catch and stop: the authority name in the message tells you which source (dladdr or maps) implicated the linker; report the launch configuration rather than retrying.","preventionTips":["Exec the binary directly instead of loading it through linker namespaces","Avoid wrappers that dlopen the program image","Reinstall via documented methods when launchers change"],"tags":["android","linker","bionic","self-update"],"backgroundTag":"runtime-linker-returned-as-executable","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}