unicity-aos/aos-ce · error · io::Error
embedded capsule has no name
Error message
embedded capsule has no name
What it means
unicity_ce_capsule_names maps over each entry of the manifest's `capsule` array and extracts its `name` string. If a capsule table has no `name` key (or it is not a string), this InvalidData io::Error is returned. It means one of the embedded distro's capsules is unnamed.
Solutions
- Add a `name` string field to every `[[capsule]]` entry in the embedded distro manifest
- Validate the manifest against the expected schema before embedding it in the distro
- Rebuild the distro from an upstream manifest rather than editing the embedded copy by hand
Example fix
# before [[capsule]] version = "1.2.0" # after [[capsule]] name = "core" version = "1.2.0"
Defensive patterns
Strategy: validation
Validate before calling
fn all_capsules_named(manifest: &str) -> bool {
toml::from_str::<toml::Value>(manifest).ok()
.and_then(|v| v.get("capsule").and_then(|c| c.as_array()).cloned())
.map(|caps| caps.iter().all(|c| c.get("name").and_then(|n| n.as_str()).map(|s| !s.is_empty()).unwrap_or(false)))
.unwrap_or(false)
} Type guard
fn capsule_name(capsule: &toml::Value) -> Option<&str> {
capsule.get("name").and_then(|n| n.as_str())
} Try / catch
match unicity_ce_capsule_names() {
Ok(names) => proceed(names),
Err(e) if e.to_string().contains("embedded capsule has no name") =>
eprintln!("a [[capsule]] entry is missing its name field"),
Err(e) => return Err(e),
} Prevention
- Add a lint/CI step asserting each [[capsule]] has a non-empty string name
- Use a typed manifest struct with a required name field instead of raw toml::Value lookups
- Validate manifests against a JSON/TOML schema before embedding
When it happens
Trigger: Calling archive_inactive_activation_state when a `[[capsule]]` entry in the embedded distro manifest omits the `name` field, or defines `name` as a non-string (e.g. an integer or inline table).
Common situations: A hand-edited manifest where a capsule table was added without a name; a schema change where the field was renamed; a malformed build-generated manifest.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- embedded distro has no capsules
- must not be empty
- embedded capsule source has no asset
- AOS capsule directory must be valid UTF-8 for the TOML…
- standalone runtime has no existing system lock; refusing an…
AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13).
Data as JSON: /api/errors/8233668a38abd6f1.
Report an issue: GitHub.
Appendix: source
Thrown at crates/unicity-aos-bootstrap/src/migration.rs:475
.map_err(|error| io::Error::new(io::ErrorKind::InvalidData, error))?;
let capsules = manifest
.get("capsule")
.and_then(toml::Value::as_array)
.ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidData,
"embedded distro has no capsules",
)
})?;
capsules
.iter()
.map(|capsule| {
capsule
.get("name")
.and_then(toml::Value::as_str)
.map(str::to_owned)
.ok_or_else(|| {
io::Error::new(io::ErrorKind::InvalidData, "embedded capsule has no name")
})
})
.collect()
}
fn archive_path(staging: &Path, relative: &Path, entries: &mut [Entry]) -> io::Result<()> {
if !is_safe_relative(relative) {
return invalid("imported activation path is unsafe");
}
let archived = Path::new(IMPORT_ARCHIVE_DIR).join(relative);
let source = staging.join(relative);
let destination = staging.join(&archived);
if destination.exists() {
return invalid("imported activation archive contains a duplicate path");
}
create_private_dir(destination.parent().expect("archive path has a parent"))?;
fs::rename(&source, &destination)?;
sync_parent(&source)?;View on GitHub (pinned to f6f22024fb)