{"record":{"id":"f0f5c7b659454dcf","repo":"unicity-aos/aos-ce","slug":"embedded-capsule-has-no-name","errorCode":null,"errorMessage":"embedded capsule has no name","messagePattern":"embedded capsule has no name","errorType":"exception","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"crates/unicity-aos-bootstrap/src/lib.rs","lineNumber":663,"sourceCode":"    let manifest = UNICITY_CE_MANIFEST\n        .parse::<toml::Value>()\n        .map_err(|error| io::Error::new(io::ErrorKind::InvalidData, error))?;\n    let capsules = manifest\n        .get(\"capsule\")\n        .and_then(toml::Value::as_array)\n        .ok_or_else(|| {\n            io::Error::new(\n                io::ErrorKind::InvalidData,\n                \"embedded distro has no capsules\",\n            )\n        })?;\n    let mut assets = Vec::with_capacity(capsules.len());\n    for capsule in capsules {\n        let package = capsule\n            .get(\"name\")\n            .and_then(toml::Value::as_str)\n            .ok_or_else(|| {\n                io::Error::new(io::ErrorKind::InvalidData, \"embedded capsule has no name\")\n            })?;\n        let source = capsule\n            .get(\"source\")\n            .and_then(toml::Value::as_str)\n            .ok_or_else(|| {\n                io::Error::new(io::ErrorKind::InvalidData, \"embedded capsule has no source\")\n            })?;\n        let relative = Path::new(source);\n        let mut components = relative.components();\n        if components.next() != Some(std::path::Component::Normal(OsStr::new(\"capsules\")))\n            || components\n                .next()\n                .and_then(|component| match component {\n                    std::path::Component::Normal(name) => Some(name),\n                    _ => None,\n                })\n                .is_none()\n            || components.next().is_some()","sourceCodeStart":645,"sourceCodeEnd":681,"githubUrl":"https://github.com/unicity-aos/aos-ce/blob/f6f22024fb1e8d122f28a1b4a9f75aee448ae839/crates/unicity-aos-bootstrap/src/lib.rs#L645-L681","documentation":"After locating the `capsule` array, capsule_assets_from_manifest iterates each capsule table and reads its `name` field as a string. This error is thrown when a `[[capsule]]` entry is missing the `name` key or the value is not a string. The name is required because the asset filename must equal `<name>.capsule`.","triggerScenarios":"A `[[capsule]]` entry in UNICITY_CE_MANIFEST omits `name`, or sets `name` to a non-string TOML value (integer, boolean, inline table, array). Raised via capsule_assets_from_manifest when invoked by capsule_dir_with, prepare_unicity_ce_init, or install_capsule_fixtures.","commonSituations":"Hand-adding a capsule entry and forgetting the name field; a script generating the manifest writing an empty or numeric identifier; a schema migration where `name` was renamed (e.g. `package`); copy-pasting an entry and deleting the name line.","solutions":["Add a string `name` field to the offending `[[capsule]]` entry matching the capsule's package name.","Ensure `name` is a plain TOML string, not a number or other type (quote it if needed).","Check the entry immediately before/after in the array — the error does not identify which entry failed, so validate each `[[capsule]]` block.","Regenerate the manifest with tooling that guarantees both `name` and `source` are present per entry."],"exampleFix":"// before\n[[capsule]]\nsource = \"capsules/foo.capsule\"\n\n// after\n[[capsule]]\nname = \"foo\"\nsource = \"capsules/foo.capsule\"","handlingStrategy":"validation","validationCode":"// Rust: check every capsule entry has a string name before calling the API\nfn ensure_capsules_named(manifest_toml: &str) -> Result<(), String> {\n    let v: toml::Value = toml::from_str(manifest_toml).map_err(|e| e.to_string())?;\n    for (i, c) in v.get(\"capsule\").and_then(toml::Value::as_array).unwrap_or(&vec![]).iter().enumerate() {\n        if c.get(\"name\").and_then(toml::Value::as_str).map(str::is_empty) != Some(false) {\n            return Err(format!(\"capsule entry #{i} is missing a non-empty string `name`\"));\n        }\n    }\n    Ok(())\n}","typeGuard":"fn capsule_name(capsule: &toml::Value) -> Option<&str> {\n    capsule.get(\"name\").and_then(toml::Value::as_str).filter(|s| !s.is_empty())\n}","tryCatchPattern":"match capsule_assets_from_manifest() {\n    Err(e) if e.to_string().contains(\"embedded capsule has no name\") => {\n        eprintln!(\"a [[capsule]] entry in the embedded manifest lacks a string `name`; fix the manifest\");\n    }\n    other => other,\n}","preventionTips":["Deserialize the manifest into a typed struct (#[derive(Deserialize)] with required name: String) so missing names fail at parse time.","Keep name and source adjacent in each [[capsule]] block to make omissions obvious in review.","CI-check the manifest fixture with a linter/schema validator before it is embedded."],"tags":["toml","manifest","missing-field","capsule"],"backgroundTag":"missing-required-config-field","analyzedSha":"f6f22024fb1e8d122f28a1b4a9f75aee448ae839","analyzedAt":"2026-09-13T03:04:44.565Z","contentChangedAt":"2026-09-13T03:04:44.565Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}