astrid-runtime/astrid · error
executable replacement set must not be empty
Error message
executable replacement set must not be empty
What it means
`validate_replacement_inputs` rejects a call to `replace_executable_set` whose `names` slice is empty. Replacing a set of zero executables is considered a caller mistake — there is nothing to stage, install, or roll back, and an empty set likely signals a bug (e.g. a failed archive listing) rather than a legitimate no-op. It fails fast with `InvalidInput` before any filesystem mutation.
Solutions
- Populate `names` with at least one executable name actually present in `extract_dir` before calling
- If the source list can legitimately be empty, guard the call site and skip or surface an application-level error instead of calling the API
- Verify the extraction step ran and produced the expected executables; fix the extraction/manifest logic that yielded an empty list
Example fix
// before
replace_executable_set(&install_dir, &extract_dir, &executables)?;
// after
if executables.is_empty() {
return Err(anyhow!("no executables extracted from release archive"));
}
replace_executable_set(&install_dir, &extract_dir, &executables)?; Defensive patterns
Strategy: validation
Validate before calling
if names.is_empty() {
return Err(anyhow!("refusing to update: no executables listed"));
} Try / catch
match replace_executable_set(&install_dir, &extract_dir, &names) {
Err(e) if e.kind() == std::io::ErrorKind::InvalidInput && names.is_empty() => {
eprintln!("no executables extracted; skipping update");
}
other => other.map_err(Into::into),
} Prevention
- Assert the executable list is non-empty right after extraction
- Treat an empty archive manifest as an extraction failure, not a valid update set
- Log the archive contents when building the name list
When it happens
Trigger: Calling `replace_executable_set(install_dir, extract_dir, &[])` — typically because the list of executables was built by filtering an archive manifest that matched nothing, or a hardcoded empty slice was passed.
Common situations: Extract step produced no matching binaries (wrong glob/prefix in archive); manifest parsing returned an empty list due to a format change; unit/integration tests accidentally pass an empty slice.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- invalid or duplicate executable name
- executable replacement directories must exist
- release contains too many assets
- release executable is redirected or not regular
- sandbox must be an absolute path, got
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/13a61641799c8213.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-core/src/platform_fs.rs:826
#[cfg(windows)]
{
windows::replace_executable_set(install_dir, extract_dir, names)
}
#[cfg(not(windows))]
{
replace_executable_set_by_rename(install_dir, extract_dir, names)
}
}
fn validate_replacement_inputs(
install_dir: &Path,
extract_dir: &Path,
names: &[&str],
) -> io::Result<()> {
if names.is_empty() {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"executable replacement set must not be empty",
));
}
if !install_dir.is_dir() || !extract_dir.is_dir() {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"executable replacement directories must exist",
));
}
let mut unique = HashSet::with_capacity(names.len());
for name in names {
let mut components = Path::new(name).components();
if !matches!(components.next(), Some(Component::Normal(_)))
|| components.next().is_some()
|| !unique.insert(*name)
{View on GitHub (pinned to affd8760f4)