{"record":{"id":"8dba50f455765c5f","repo":"astrid-runtime/astrid","slug":"legacy-capsule-directory-id-does-not-match-manif","errorCode":null,"errorMessage":"legacy capsule directory {id} does not match manifest id {}","messagePattern":"legacy capsule directory (.+?) does not match manifest id (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-capsule-install/src/storage/migration.rs","lineNumber":134,"sourceCode":"    let mut children = read_dir_sorted(&native)?;\n    let mut report = LegacyCapsuleMigrationReport::default();\n    let registry = store.capsules();\n    let owner = StateOwner::Principal(uid);\n    for (target, target_metadata) in children.drain(..) {\n        if target_metadata.file_type().is_symlink() || !target_metadata.is_dir() {\n            bail!(\n                \"legacy capsule entry is not a regular directory: {}\",\n                target.display()\n            );\n        }\n        let id = target\n            .file_name()\n            .and_then(|name| name.to_str())\n            .ok_or_else(|| anyhow::anyhow!(\"legacy capsule entry has a non-UTF-8 name\"))?;\n        let manifest = astrid_capsule::discovery::load_manifest(&target.join(\"Capsule.toml\"))\n            .with_context(|| format!(\"read legacy capsule manifest {id}\"))?;\n        if manifest.package.name != id {\n            bail!(\n                \"legacy capsule directory {id} does not match manifest id {}\",\n                manifest.package.name\n            );\n        }\n        let meta_bytes = fs::read(target.join(\"meta.json\"))\n            .with_context(|| format!(\"read legacy capsule metadata {id}\"))?;\n        let meta: CapsuleMeta = serde_json::from_slice(&meta_bytes)\n            .with_context(|| format!(\"decode legacy capsule metadata {id}\"))?;\n        if meta.version != manifest.package.version {\n            bail!(\"legacy capsule metadata version differs for {id}\");\n        }\n        // Released pre-authority installs are admitted only through the\n        // existing one-time verifier. It pins their exact manifest,\n        // capabilities, and executable before any durable publication.\n        // Relocated homes keep receipts hashed from a previous absolute\n        // path; rebind a unique leftover onto this target first.\n        rebind_relocated_legacy_authority_receipt(home, &target, &manifest, workspace_targets)\n            .with_context(|| format!(\"rebind relocated leftover authority for {id}\"))?;","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-capsule-install/src/storage/migration.rs#L116-L152","documentation":"Each legacy capsule directory name is treated as the capsule id, and migration cross-checks it against the package name declared in the capsule's Capsule.toml manifest. A mismatch means the directory no longer reliably identifies the capsule, so migration refuses to proceed for that entry.","triggerScenarios":"The capsule directory was renamed manually after install; the manifest's package.name was edited in place; the directory was copied under a different name (e.g. my-capsule-2, my-capsule-backup).","commonSituations":"Users renaming folders to keep old versions around; hand-edited Capsule.toml during development; restored backups that renamed directories.","solutions":["Rename the directory so it exactly matches manifest.package.name in its Capsule.toml","Restore the original package.name in Capsule.toml to match the directory name","Remove the stale/mismatched directory if it is a leftover copy","Reinstall the capsule cleanly so directory and manifest agree"],"exampleFix":"# before\ncapsules/my-capsule-backup/Capsule.toml -> name = \"my-capsule\"\n# after\nmv capsules/my-capsule-backup capsules/my-capsule","handlingStrategy":"validation","validationCode":"fn ids_agree(capsule_dir: &Path) -> Result<(), String> {\n    let id = capsule_dir.file_name().unwrap().to_string_lossy().to_string();\n    let manifest = astrid_capsule::discovery::load_manifest(&capsule_dir.join(\"Capsule.toml\"))\n        .map_err(|e| e.to_string())?;\n    if manifest.package.name != id { return Err(format!(\"dir {id} != manifest {}\", manifest.package.name)); }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = migrate_native_capsules(home, store) {\n    if e.to_string().contains(\"does not match manifest id\") {\n        eprintln!(\"rename the capsule directory to match its Capsule.toml name, then retry\");\n    } else { return Err(e); }\n}","preventionTips":["Keep directory names identical to manifest.package.name","Never edit package.name in an installed capsule's Capsule.toml in place","Store old copies under a separate backup root, not inside the capsules directory","Reinstall rather than renaming installed capsules"],"tags":["migration","manifest","id-mismatch","capsule"],"backgroundTag":"invalid-identifier","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}