unicity-aos/aos-ce · error · io::Error
completed product runtime is not installed
Error message
completed product runtime is not installed
What it means
validate_completed_target mirrors validate_target for the completed-migration path: it requires the target to exist (symlink_metadata) and be a real directory. A missing target maps to this InvalidInput error with the "completed product runtime" wording. It indicates the post-migration runtime installation is absent.
Solutions
- Ensure the migration step that installs the completed runtime actually ran and wrote the target directory
- Re-run the migration to completion before invoking the completed-state validation
- Verify the receipt's recorded target matches the actual installed path
Example fix
// before validate_completed_target(&target, &bin, &receipt)?; // target absent // after assert!(target.symlink_metadata().is_ok(), "runtime not installed"); validate_completed_target(&target, &bin, &receipt)?;
Defensive patterns
Strategy: validation
Validate before calling
fn completed_runtime_installed(target: &std::path::Path) -> bool {
std::fs::symlink_metadata(target)
.map(|m| m.is_dir())
.unwrap_or(false)
} Try / catch
match migrate_runtime(&target, ...) {
Ok(()) => {},
Err(e) if e.to_string().contains("completed product runtime is not installed") =>
eprintln!("migration incomplete; re-run to install the completed runtime"),
Err(e) => return Err(e),
} Prevention
- Only invoke completed-state validation after a migration run reported success
- Persist migration state so interrupted runs can resume instead of being validated early
- Verify the receipt's target path matches the machine's actual layout
When it happens
Trigger: Calling migrate_runtime's completed-path validation when the final target directory has not been created or was deleted before validation runs.
Common situations: A migration run interrupted before the target was installed; running the completed-state validation against a machine where only staging exists; a wrong receipt/target pairing.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- standalone runtime has no existing system lock; refusing an…
- failed to preserve imported activation state
- failed to validate ephemeral state exclusion
- failed to inspect imported distro locks
- imported principal home contains a non-UTF-8 name
AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13).
Data as JSON: /api/errors/4e8de267a9fbd24a.
Report an issue: GitHub.
Appendix: source
Thrown at crates/unicity-aos-bootstrap/src/migration.rs:658
for entry in fs::read_dir(target)? {
let entry = entry?;
let path = entry.path();
let metadata = fs::symlink_metadata(&path)?;
if path != bin || metadata.file_type().is_symlink() || !metadata.is_dir() {
return invalid("product runtime home contains data; migration refuses to merge state");
}
}
Ok(())
}
fn validate_completed_target(
target: &Path,
release_runtime_bin: &Path,
_receipt: &Receipt,
) -> io::Result<()> {
validate_release_runtime_bin(release_runtime_bin)?;
let target_metadata = fs::symlink_metadata(target).map_err(|_| {
io::Error::new(
io::ErrorKind::InvalidInput,
"completed product runtime is not installed",
)
})?;
if target_metadata.file_type().is_symlink() || !target_metadata.is_dir() {
return invalid("completed product runtime must be a real directory");
}
let bin = target.join("bin");
match fs::symlink_metadata(&bin) {
Ok(bin_metadata) => {
if bin_metadata.file_type().is_symlink() || !bin_metadata.is_dir() {
return invalid("completed product runtime bin must be a real directory");
}
for entry in fs::read_dir(&bin)? {
let entry = entry?;
let name = entry.file_name();
if RUNTIME_EXECUTABLE_NAMES
.iter()View on GitHub (pinned to f6f22024fb)