{"record":{"id":"4fd5fc0bd244becd","repo":"herdrdev/herdr","slug":"download-failed-err","errorCode":null,"errorMessage":"download failed: {err}","messagePattern":"download failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/remote/attach.rs","lineNumber":1441,"sourceCode":"    stdout\n        .lines()\n        .next()\n        .map(str::trim)\n        .is_some_and(|path| path.ends_with(\"/.local/bin/herdr\"))\n}\n\nfn download_release_asset(platform: &RemotePlatform) -> io::Result<InstallSource> {\n    let asset_key = platform.asset_key();\n    let asset = remote_release_asset(&asset_key)?;\n\n    let dir = private_download_dir(&asset_key)?;\n    let path = dir.join(\"herdr.tmp\");\n    let status = crate::noninteractive_process::curl_command()\n        .args([\"-sfL\", \"--max-time\", \"120\", \"-o\"])\n        .arg(&path)\n        .arg(&asset.url)\n        .status()\n        .map_err(|err| io::Error::new(err.kind(), format!(\"download failed: {err}\")))?;\n    if !status.success() {\n        let _ = fs::remove_dir_all(&dir);\n        return Err(io::Error::other(\"download failed\"));\n    }\n    if let Some(expected) = &asset.sha256 {\n        if let Err(err) = crate::checksum::verify_sha256(&path, expected) {\n            let _ = fs::remove_dir_all(&dir);\n            return Err(io::Error::new(\n                err.kind(),\n                format!(\"downloaded remote asset checksum verification failed: {err}\"),\n            ));\n        }\n    }\n\n    Ok(InstallSource::temporary(path, dir))\n}\n\nfn fetch_remote_manifest(url: &str) -> io::Result<Vec<u8>> {","sourceCodeStart":1423,"sourceCodeEnd":1459,"githubUrl":"https://github.com/herdrdev/herdr/blob/f457cff4f2648eee85d176f8a41861241d4e8428/src/remote/attach.rs#L1423-L1459","documentation":"This error wraps a failure to spawn the curl process used to download the remote herdr asset (curl_command().args([-sfL, --max-time 120, ...]).status()). The spawn error kind is preserved; curl itself failing produces the separate 'download failed' message without {err}.","triggerScenarios":"curl is not installed on PATH, is not executable, or the process cannot be spawned (resource limits, exec format error) while downloading the remote release asset to a temp herdr.tmp file.","commonSituations":"Minimal containers or slim images without curl, PATH stripped in the SSH/non-interactive environment, or a corrupted curl binary.","solutions":["Verify curl is installed and on PATH: curl --version","Install curl (apt/brew/apk) on the machine performing the download","If PATH is stripped in non-interactive SSH, configure an absolute curl path or fix the environment","Retry the attach after fixing curl"],"exampleFix":"# before: container without curl\n# after\napt-get update && apt-get install -y curl","handlingStrategy":"fallback","validationCode":"fn curl_available() -> bool {\n    std::process::Command::new(\"curl\")\n        .arg(\"--version\")\n        .output()\n        .map(|o| o.status.success())\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"match download_asset(url) {\n    Err(e) if e.to_string().starts_with(\"download failed\") && !curl_available() => {\n        fetch_with_alternative_http_client(url)\n    }\n    r => r,\n}","preventionTips":["Ensure curl is installed in all environments that run herdr remote attach","Verify curl is on PATH in non-interactive SSH sessions"],"tags":["download","curl","spawn","dependency","rust"],"backgroundTag":"curl-spawn-failed","analyzedSha":"f457cff4f2648eee85d176f8a41861241d4e8428","analyzedAt":"2026-08-28T15:41:09.197Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}