unicity-aos/aos-ce · error · io::Error
failed to preserve imported activation state
Error message
failed to preserve imported activation state: {error} What it means
`migrate_runtime` calls `archive_inactive_activation_state` on the staging copy of the imported runtime and wraps any failure in an `io::Error` preserving the original kind, prefixed with "failed to preserve imported activation state". This means inactive activation-state homes could not be archived — typically due to I/O errors or invalid names encountered while walking the imported state.
Solutions
- Read the wrapped inner error in the message after the prefix — it names the actual failing operation (path, permission, encoding) to fix.
- Fix permissions on the source runtime's `homes`/activation-state directories so they are readable by the migrating user.
- Rename any non-UTF-8 file/directory names under the imported principal homes and capsule installations before migrating.
- Re-create or repair the source activation state (e.g. by re-syncing from the live runtime) if directories are corrupted, then retry.
Defensive patterns
Strategy: try-catch
Validate before calling
check_source_readable(source.join("state/homes"))?;
check_all_names_utf8(source.join("state/homes"))?; Try / catch
if let Some(io_err) = err.downcast_ref::<io::Error>() {
let inner = io_err.to_string();
if let Some(inner_msg) = inner.strip_prefix("failed to preserve imported activation state: ") {
eprintln!("underlying cause: {inner_msg}");
}
} Prevention
- Run the migration as a user with read access to all activation-state directories.
- Ensure all names under homes/ and capsule dirs are UTF-8 before migrating.
- Stop the source runtime so state is not mutated during archiving.
When it happens
Trigger: Any error surfaced from `archive_inactive_activation_state` while iterating `homes`/capsule directories during `migrate_runtime` — e.g. unreadable directories, permission failures, or the non-UTF-8 name errors (errors 38/39).
Common situations: Importing from a source with restrictive permissions on principal home directories, a partially-corrupted activation state, or filesystems that return errors on read_dir during copy.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- standalone runtime has no existing system lock; refusing an…
- failed to validate ephemeral state exclusion
- failed to inspect imported distro locks
- imported principal home contains a non-UTF-8 name
- imported capsule installation contains a non-UTF-8 name
AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13).
Data as JSON: /api/errors/ed809f44ce6efc13.
Report an issue: GitHub.
Appendix: source
Thrown at crates/unicity-aos-bootstrap/src/migration.rs:272
"a previous migration staging directory could not be recovered automatically",
);
}
let result = (|| {
create_private_dir(&staging)?;
let mut entries = Vec::new();
copy_etc_state(&source, &staging, &mut entries)?;
for name in PERSISTENT_TOP_LEVEL {
copy_if_present(
&source.join(name),
&staging.join(name),
Path::new(name),
&mut entries,
)?;
}
copy_wasm_blobs(&source.join("bin"), &staging.join("bin"), &mut entries)?;
archive_inactive_activation_state(&staging, &mut entries).map_err(|error| {
io::Error::new(
error.kind(),
format!("failed to preserve imported activation state: {error}"),
)
})?;
ensure_no_ephemeral_data(&staging).map_err(|error| {
io::Error::new(
error.kind(),
format!("failed to validate ephemeral state exclusion: {error}"),
)
})?;
entries.sort_by(|left, right| left.path.cmp(&right.path));
let legacy_distros = legacy_distros(&staging).map_err(|error| {
io::Error::new(
error.kind(),
format!("failed to inspect imported distro locks: {error}"),
)
})?;
let receipt = Receipt {View on GitHub (pinned to f6f22024fb)