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

  1. Re-run the install with `--allow-unsigned` if you built the capsule yourself and accept the risk.
  2. 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.
  3. 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

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


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/17eb3bbea81d483a. Report an issue: GitHub.