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

  1. Read the wrapped inner error in the message after the prefix — it names the actual failing operation (path, permission, encoding) to fix.
  2. Fix permissions on the source runtime's `homes`/activation-state directories so they are readable by the migrating user.
  3. Rename any non-UTF-8 file/directory names under the imported principal homes and capsule installations before migrating.
  4. 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

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


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)