unicity-aos/aos-ce · error · io::Error
embedded capsule source does not match package
Error message
embedded capsule source does not match package {package} What it means
This error is thrown by capsule_assets_from_manifest when a capsule entry in the embedded Community Edition TOML manifest has a `source` path whose filename is not `<package>.capsule`, where `<package>` is the entry's `name` field. The bootstrap library enforces a strict naming convention so that embedded capsule assets can be located and validated deterministically; any drift between the package name and the asset filename breaks that invariant.
Solutions
- Rename the asset in the `source` path so its filename is exactly `{name}.capsule` for that manifest entry
- Or update the entry's `name` field to match the existing filename (minus the .capsule extension)
- Re-run prepare_unicity_ce_init to confirm the embedded manifest passes validation
Example fix
// before
capsule = [{ name = "kernel-core", source = "capsules/kernel-core-v2.capsule" }]
// after
capsule = [{ name = "kernel-core", source = "capsules/kernel-core.capsule" }] Defensive patterns
Strategy: validation
Validate before calling
fn capsule_source_matches(capsule: &toml::Value) -> bool {
let name = capsule.get("name").and_then(|v| v.as_str());
let source = capsule.get("source").and_then(|v| v.as_str());
match (name, source) {
(Some(n), Some(s)) => {
std::path::Path::new(s).file_name().map(|f| f.to_string_lossy())
== Some(format!("{n}.capsule"))
}
_ => false,
}
} Type guard
fn is_valid_capsule_entry(c: &toml::Value) -> bool {
c.get("name").and_then(|v| v.as_str()).is_some()
&& c.get("source").and_then(|v| v.as_str()).is_some()
} Try / catch
match bootstrap::prepare_unicity_ce_init(&home) {
Err(e) if e.to_string().contains("does not match package") => {
eprintln!("Manifest entry name/source mismatch: {e}");
}
Err(e) => return Err(e),
Ok(v) => v,
} Prevention
- Always keep the asset filename as exactly `{name}.capsule` in manifest entries
- Add a CI check that validates every [[capsule]] entry's name/source pairing
- Avoid renaming packages without renaming their .capsule assets in the same commit
When it happens
Trigger: Editing the embedded UNICITY_CE_MANIFEST so a `[capsule]` entry's `source` filename does not equal the `name` field plus the `.capsule` extension (e.g. name="foo", source="capsules/foo_v2.capsule"). Any call to capsule_dir_with, prepare_unicity_ce_init, or install_capsule_fixtures then fails.
Common situations: Renaming a capsule package without renaming its .capsule asset file (or vice versa); hand-editing the embedded manifest; adding a new capsule entry with a versioned or suffixed filename; copy-pasting a capsule entry and updating only one of the two fields.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- embedded distro selects duplicate capsule asset
- embedded capsule source has no asset
- AOS capsule directory is unavailable at
- AOS capsule directory must be a real directory
- AOS capsule directory contains a non-regular entry
AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13).
Data as JSON: /api/errors/bcabe850302c4bc7.
Report an issue: GitHub.
Appendix: source
Thrown at crates/unicity-aos-bootstrap/src/lib.rs:698
.is_none()
|| components.next().is_some()
|| relative.extension() != Some(OsStr::new("capsule"))
{
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("embedded capsule source is not canonical: {source}"),
));
}
let asset = relative
.file_name()
.expect("validated capsule source has a filename")
.to_str()
.ok_or_else(|| {
io::Error::new(io::ErrorKind::InvalidData, "capsule asset is not UTF-8")
})?
.to_owned();
if asset != format!("{package}.capsule") {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("embedded capsule source does not match package {package}"),
));
}
if assets.contains(&asset) {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("embedded distro selects duplicate capsule asset {asset}"),
));
}
assets.push(asset);
}
Ok(assets)
}
fn validate_capsule_dir(path: &Path, expected: &[String]) -> io::Result<PathBuf> {
let metadata = fs::symlink_metadata(path).map_err(|error| {
io::Error::new(View on GitHub (pinned to f6f22024fb)