unicity-aos/aos-ce · error · io::Error

AOS capsule set differs from Community Edition; expected

Error message

AOS capsule set differs from Community Edition; expected {}, found {}

What it means

Thrown by validate_capsule_dir when the sorted set of filenames in the capsule directory does not equal the expected set derived from the embedded Community Edition manifest. Note the message prints only the expected and found counts; the library enforces an exact match to guarantee the on-disk capsule set mirrors the embedded distro.

Solutions

  1. Delete the capsule directory and regenerate it with install_capsule_fixtures so it matches the embedded manifest
  2. Compare directory contents against the embedded manifest's `[capsule]` source filenames and reconcile (add missing, remove extra)
  3. If upgrading, clear the stale capsule directory before running prepare_unicity_ce_init

Example fix

// before
$ ls ~/.aos/capsules
auth.capsule  kernel-core.capsule  stale-old.capsule
// after
$ rm -rf ~/.aos/capsules && rerun install_capsule_fixtures
$ ls ~/.aos/capsules
auth.capsule  kernel-core.capsule
Defensive patterns

Strategy: validation

Validate before calling

fn capsule_set_matches(dir: &std::path::Path, expected: &[String]) -> bool {
    let mut actual: Vec<String> = std::fs::read_dir(dir)
        .map(|rd| rd.filter_map(|e| e.ok())
            .filter_map(|e| e.file_name().into_string().ok())
            .collect())
        .unwrap_or_default();
    actual.sort();
    let mut exp = expected.to_vec();
    exp.sort();
    actual == exp
}

Try / catch

match bootstrap::capsule_dir_with(&home) {
    Err(e) if e.to_string().contains("capsule set differs") => {
        eprintln!("Capsule directory is stale or modified; regenerate it: {e}");
        // fs::remove_dir_all(capsules)?; install_capsule_fixtures(...)?;
    }
    Err(e) => return Err(e),
    Ok(dir) => dir,
}

Prevention

When it happens

Trigger: Extra stale .capsule files left in the directory, missing files that the embedded manifest requires, renamed files, or an embedded-manifest version differing from the installed capsule set — any capsule_dir_with / prepare_unicity_ce_init call then fails.

Common situations: Upgrading the application (new embedded manifest) while keeping an old capsule directory; manually deleting or adding capsule files; a partially completed install leaving a partial set.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13). Data as JSON: /api/errors/34147b639706ed9c. Report an issue: GitHub.

Appendix: source

Thrown at crates/unicity-aos-bootstrap/src/lib.rs:759

                format!(
                    "AOS capsule directory contains a non-regular entry: {}",
                    entry.path().display()
                ),
            ));
        }
        let name = entry.file_name().into_string().map_err(|_| {
            io::Error::new(
                io::ErrorKind::InvalidInput,
                "AOS capsule directory contains a non-UTF-8 entry",
            )
        })?;
        actual.push(name);
    }
    actual.sort();
    let mut expected = expected.to_vec();
    expected.sort();
    if actual != expected {
        return Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            format!(
                "AOS capsule set differs from Community Edition; expected {}, found {}",
                expected.len(),
                actual.len()
            ),
        ));
    }
    Ok(canonical)
}

fn materialize_manifest(capsule_dir: &Path) -> io::Result<String> {
    let mut manifest = UNICITY_CE_MANIFEST
        .parse::<toml::Value>()
        .map_err(|error| io::Error::new(io::ErrorKind::InvalidData, error))?;
    let capsules = manifest
        .get_mut("capsule")
        .and_then(toml::Value::as_array_mut)

View on GitHub (pinned to f6f22024fb)