{"record":{"id":"0ed1e518789b604b","repo":"astrid-runtime/astrid","slug":"release-archive-is-missing-name-error","errorCode":null,"errorMessage":"release archive is missing '{name}': {error}","messagePattern":"release archive is missing '(.+?)': (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-core/src/platform_fs.rs","lineNumber":853,"sourceCode":"        ));\n    }\n\n    let mut unique = HashSet::with_capacity(names.len());\n    for name in names {\n        let mut components = Path::new(name).components();\n        if !matches!(components.next(), Some(Component::Normal(_)))\n            || components.next().is_some()\n            || !unique.insert(*name)\n        {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidInput,\n                format!(\"invalid or duplicate executable name '{name}'\"),\n            ));\n        }\n\n        let source = extract_dir.join(name);\n        let metadata = std::fs::symlink_metadata(&source).map_err(|error| {\n            io::Error::new(\n                error.kind(),\n                format!(\"release archive is missing '{name}': {error}\"),\n            )\n        })?;\n        if metadata.file_type().is_symlink() || !metadata.is_file() {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidInput,\n                format!(\"release executable is redirected or not regular: {name}\"),\n            ));\n        }\n    }\n    Ok(())\n}\n\n#[cfg(not(windows))]\nfn replace_executable_set_by_rename(\n    install_dir: &Path,\n    extract_dir: &Path,","sourceCodeStart":835,"sourceCodeEnd":871,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-core/src/platform_fs.rs#L835-L871","documentation":"Every listed executable must physically exist in `extract_dir`. When `std::fs::symlink_metadata(extract_dir.join(name))` fails, `validate_replacement_inputs` re-raises the OS error wrapped as `release archive is missing '<name>'`. The set is rejected before any live files are touched, so the current installation stays intact.","triggerScenarios":"Calling `replace_executable_set` with a name absent from `extract_dir` — archive extraction skipped that file, the name was misquoted or case-mismatches (`Astrid` vs `astrid` on a case-sensitive filesystem), or the extracted platform suffix (e.g. `.exe`) was stripped from the name.","commonSituations":"Extracting a truncated or partially downloaded archive; wrong architecture/platform archive extracted while the name list came from a manifest for another platform; names built from a previous release's manifest that no longer match.","solutions":["Verify the file exists at `extract_dir.join(name)` and re-run extraction if it is missing","Check the name's exact case and platform suffix against the extracted archive contents (list the dir and match)","Use the same manifest/archive pair for extraction and the `names` list to avoid cross-release mismatches"],"exampleFix":"// before\nreplace_executable_set(&install_dir, &extract_dir, &[\"astrid\"])?;\n// after\nlet names: Vec<&str> = if cfg!(windows) { &[\"astrid.exe\"] } else { &[\"astrid\"] };\nreplace_executable_set(&install_dir, &extract_dir, names)?;","handlingStrategy":"validation","validationCode":"let missing: Vec<_> = names.iter()\n    .filter(|n| !extract_dir.join(n).exists())\n    .collect();\nif !missing.is_empty() {\n    return Err(anyhow!(\"missing from extract dir: {missing:?}\"));\n}","typeGuard":null,"tryCatchPattern":"match replace_executable_set(&install_dir, &extract_dir, names) {\n    Err(e) if e.to_string().starts_with(\"release archive is missing\") => {\n        eprintln!(\"re-extract the archive; {e}\");\n    }\n    other => other.map_err(Into::into),\n}","preventionTips":["Verify the archive checksum and completeness after download/extraction","Match name lists and archives from the same release manifest","Check case-sensitivity and platform suffixes (.exe) when constructing names","List extract_dir contents and diff against names before updating"],"tags":["filesystem","file-not-found","self-update","archive"],"backgroundTag":"file-not-found","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}