astrid-runtime/astrid · error
capsule ' ' is not present in the shuttle (offline install…
Error message
capsule '{}' is not present in the shuttle (offline install cannot fetch it) What it means
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.
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
Example fix
// before (shuttle missing 'net-tools' added later to the manifest) // build shuttle from old distro, install with new Distro.toml -> error // after // astrid distro pack --output /media/shuttle # regenerate shuttle from current manifest
Defensive patterns
Strategy: validation
Validate before calling
let file = shuttle::capsule_mirror_path(mirror, &cap.name);
if !file.is_file() {
return Err(anyhow!("capsule '{}' missing from shuttle mirror", cap.name));
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- capsule ' ' is missing from the shuttle mirror
- an incomplete capsule authority update exists at
- astrid-build failed with exit code
- astrid-build produced no .capsule archive.
- authority receipt has an empty capsule id
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/c5d0af64d73a9669.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-cli/src/commands/distro/shuttle_install.rs:215
/// Install each selected capsule from the verified mirror and return
/// the resolved [`LockedCapsule`] entries for the user's lock.
///
/// Capsule archive bytes were already validated against the sealed lock up
/// front by [`verify_capsule_hashes`]. The user's lock records the version and
/// content-addressed WASM hash reported by the checked install itself.
async fn install_selected_capsules(
principal: &astrid_core::PrincipalId,
mirror: &Path,
selected: &[super::manifest::DistroCapsule],
sealed_capsules: &std::collections::HashMap<&str, &LockedCapsule>,
distro_id: &str,
) -> anyhow::Result<Vec<LockedCapsule>> {
let mut locked: Vec<LockedCapsule> = Vec::with_capacity(selected.len());
for cap in selected {
let file = shuttle::capsule_mirror_path(mirror, &cap.name);
if !file.is_file() {
bail!(
"capsule '{}' is not present in the shuttle (offline install cannot fetch it)",
cap.name
);
}
// The sealed lock entry carries the truly-resolved ref. Nothing is
// resolved or guessed during offline installation.
let sealed = sealed_capsules.get(cap.name.as_str());
let resolved_ref = sealed.and_then(|c| c.resolved_ref.clone());
let source_digest = source_digest(&file)
.with_context(|| format!("hash capsule {} for provenance", cap.name))?;
let installed =
crate::commands::capsule::install_daemon::install_local_via_daemon_for_target(
&file.to_string_lossy(),
&[],
principal,
Some(CapsuleInstallProvenance {
distro: Some(distro_id.to_owned()),View on GitHub (pinned to affd8760f4)