astrid-runtime/astrid · warning
shuttle for '{distro_id}' is unsigned (no [distro.signing] o
Error message
shuttle for '{distro_id}' is unsigned (no [distro.signing] or Distro.sig) — refusing. Re-run with --allow-unsigned to install anyway. What it means
`unsigned_shuttle_may_install` enforces shuttle signing policy: if the unpacked distro has neither `[distro.signing]` metadata nor a `Distro.sig` signature file, installation is refused unless the user explicitly opts in with `--allow-unsigned`. This protects against installing tampered or unverified distros.
Source
Thrown at crates/astrid-cli/src/commands/distro/shuttle_install.rs:181
distro: DistroLockMeta {
id: distro_id,
version: manifest.distro.version,
resolved_at: chrono::Utc::now().to_rfc3339(),
},
capsules: locked,
manifest_hash: lock.manifest_hash,
};
write_lock_to_daemon(&principal, &user_lock).await?;
eprintln!();
eprintln!("{}", Theme::success("Offline installation complete."));
Ok(())
}
/// Decide whether an unsigned shuttle may proceed to the warning path.
fn unsigned_shuttle_may_install(distro_id: &str, opts: &InitOpts) -> anyhow::Result<()> {
if !opts.allow_unsigned {
bail!(
"shuttle for '{distro_id}' is unsigned (no [distro.signing] or Distro.sig) — \
refusing. Re-run with --allow-unsigned to install anyway."
);
}
Ok(())
}
/// Product apply is pin-first; ordinary signed shuttles may first-pin.
fn trust_policy(opts: &InitOpts) -> trust::TrustPolicy {
if opts.require_signed {
trust::TrustPolicy::RequireExistingPin
} else {
trust::TrustPolicy::TofuFirstPin
}
}
/// Install each selected capsule from the verified mirror and return
/// the resolved [`LockedCapsule`] entries for the user's lock.View on GitHub (pinned to affd8760f4)
Solutions
- Re-run the install with `--allow-unsigned` if you built the capsule yourself and accept the risk.
- Sign the capsule: generate a 32-byte ed25519 key and run the seal/sign command so `[distro.signing]`/`Distro.sig` are embedded, then install normally.
- Verify you have the latest capsule — re-download/re-pack if the signature file is missing from an otherwise signed distro.
Example fix
// before $ astrid init --shuttle app.shuttle # unsigned -> refused // after $ astrid distro seal --key signing.key ... # produce signature $ astrid init --shuttle app.shuttle # or --allow-unsigned
Defensive patterns
Strategy: try-catch
Validate before calling
// check for signature inputs before install
let signed = capsule_contains("Distro.sig") || manifest_has("[distro.signing]");
if !signed && !opts.allow_unsigned {
eprintln!("capsule is unsigned; sign it or pass --allow-unsigned");
std::process::exit(1);
} Try / catch
match install_from_shuttle(&path, &opts) {
Err(e) if e.to_string().contains("allow-unsigned") => {
eprintln!("capsule unsigned: seal it with a signing key or rerun with --allow-unsigned");
}
other => other?,
} Prevention
- Always seal capsules with an ed25519 key after packing
- Only use --allow-unsigned for capsules you built locally
- Verify signatures on every capsule from third parties
- Upgrade old capsules produced before signing was enforced
When it happens
Trigger: Calling `install_from_shuttle` on a capsule with no signature and no signing metadata, without `--allow-unsigned`; the function is reached when signature verification inputs are absent entirely.
Common situations: Installing a self-built capsule that was packed without a signing key; a distro author forgot to run the seal/sign step; older capsules produced before signing was introduced.
Related errors
- installed authority receipt does not match capsule '{capsule
- capsule content changed after authority decision (approved {
- capsule provenance changed after authority decision
- capsule identity or version changed after authority decision
- capsule manifest changed after authority decision
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/17eb3bbea81d483a.
Report an issue: GitHub.