{"record":{"id":"c5d0af64d73a9669","repo":"astrid-runtime/astrid","slug":"capsule-is-not-present-in-the-shuttle-offlin","errorCode":null,"errorMessage":"capsule '{}' is not present in the shuttle (offline install cannot fetch it)","messagePattern":"capsule '(.+?)' is not present in the shuttle \\(offline install cannot fetch it\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/distro/shuttle_install.rs","lineNumber":215,"sourceCode":"\n/// Install each selected capsule from the verified mirror and return\n/// the resolved [`LockedCapsule`] entries for the user's lock.\n///\n/// Capsule archive bytes were already validated against the sealed lock up\n/// front by [`verify_capsule_hashes`]. The user's lock records the version and\n/// content-addressed WASM hash reported by the checked install itself.\nasync fn install_selected_capsules(\n    principal: &astrid_core::PrincipalId,\n    mirror: &Path,\n    selected: &[super::manifest::DistroCapsule],\n    sealed_capsules: &std::collections::HashMap<&str, &LockedCapsule>,\n    distro_id: &str,\n) -> anyhow::Result<Vec<LockedCapsule>> {\n    let mut locked: Vec<LockedCapsule> = Vec::with_capacity(selected.len());\n    for cap in selected {\n        let file = shuttle::capsule_mirror_path(mirror, &cap.name);\n        if !file.is_file() {\n            bail!(\n                \"capsule '{}' is not present in the shuttle (offline install cannot fetch it)\",\n                cap.name\n            );\n        }\n\n        // The sealed lock entry carries the truly-resolved ref. Nothing is\n        // resolved or guessed during offline installation.\n        let sealed = sealed_capsules.get(cap.name.as_str());\n        let resolved_ref = sealed.and_then(|c| c.resolved_ref.clone());\n        let source_digest = source_digest(&file)\n            .with_context(|| format!(\"hash capsule {} for provenance\", cap.name))?;\n        let installed =\n            crate::commands::capsule::install_daemon::install_local_via_daemon_for_target(\n                &file.to_string_lossy(),\n                &[],\n                principal,\n                Some(CapsuleInstallProvenance {\n                    distro: Some(distro_id.to_owned()),","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/distro/shuttle_install.rs#L197-L233","documentation":"During an offline install from a shuttle (a removable mirror of a distro), install_selected_capsules walks the selected capsule list and resolves each capsule to its mirror file via capsule_mirror_path. If the selected capsule's archive file does not exist on the shuttle, it bails immediately because an offline install cannot download anything. This is a fail-fast guard preventing partial installs from an incomplete mirror.","triggerScenarios":"Calling install_from_shuttle (offline install) with a selected capsule whose name has no corresponding archive in the shuttle mirror directory — e.g. the capsule was added to Distro.toml after the shuttle was built, or the file was deleted/renamed on the removable media.","commonSituations":"Operator builds a shuttle from an older manifest, then installs from a newer Distro.toml listing extra capsules; shuttle media is partially copied or corrupted; capsule renamed in the manifest but shuttle rebuilt with the old set.","solutions":["Rebuild/refresh the shuttle so its mirror contains every capsule selected in the archive's Distro.toml","Check the capsule name in Distro.toml for typos and verify the file exists under the mirror path on the shuttle","Remove the missing capsule from the install selection if it is not needed"],"exampleFix":"// before (shuttle missing 'net-tools' added later to the manifest)\n// build shuttle from old distro, install with new Distro.toml -> error\n// after\n// astrid distro pack --output /media/shuttle   # regenerate shuttle from current manifest","handlingStrategy":"validation","validationCode":"let file = shuttle::capsule_mirror_path(mirror, &cap.name);\nif !file.is_file() {\n    return Err(anyhow!(\"capsule '{}' missing from shuttle mirror\", cap.name));\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Regenerate the shuttle after every Distro.toml capsule-set change","Verify the mirror contents against the lock before transport","Keep capsule names in the manifest and shuttle build sourced from one file"],"tags":["offline-install","shuttle","missing-file","capsule"],"backgroundTag":"resource-not-found","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}