astrid-runtime/astrid · error

capsule '{}': branch/rev require building from source and ar

Error message

capsule '{}': branch/rev require building from source and are not allowed in a distro manifest — pin a released `version` or `tag` (git-ref installs are available via `astrid capsule install`).

What it means

Distros compose *released* capsules so they can be seeded offline/headless without a toolchain. `branch` and `rev` selectors would require compiling from a git ref, defeating that purpose, so validate_manifest rejects any capsule specifying either. Git-ref installs remain available via the standalone `astrid capsule install` command.

Source

Thrown at crates/astrid-cli/src/commands/distro/validate.rs:148

    let mut seen_names = HashSet::new();
    for cap in &manifest.capsules {
        if !is_valid_id(&cap.name) {
            anyhow::bail!(
                "capsule name '{}' is invalid (must match ^[a-z][a-z0-9-]*$)",
                cap.name,
            );
        }
        if !seen_names.insert(&cap.name) {
            anyhow::bail!("duplicate capsule name '{}'", cap.name);
        }
        // Distros compose *released* capsules. `branch`/`rev` selectors
        // can only be honored by compiling from a git ref — the exact
        // toolchain dependency offline/headless distro seeding exists to
        // remove. Reject them: a distro must pin a released `version` or
        // `tag`. (Git-ref installs remain available via the standalone
        // `astrid capsule install` command.)
        if cap.branch.is_some() || cap.rev.is_some() {
            anyhow::bail!(
                "capsule '{}': branch/rev require building from source and are not allowed in a \
                 distro manifest — pin a released `version` or `tag` (git-ref installs are \
                 available via `astrid capsule install`).",
                cap.name,
            );
        }
        let version = cap.version.trim();
        if cap.version != version {
            anyhow::bail!(
                "capsule '{}': version must not contain surrounding whitespace",
                cap.name
            );
        }
        if !version.is_empty() && Version::parse(version).is_err() {
            anyhow::bail!(
                "capsule '{}': version '{}' is not valid semver",
                cap.name,
                cap.version

View on GitHub (pinned to affd8760f4)

Solutions

  1. Replace `branch`/`rev` with a released `version` (exact semver) or `tag` field.
  2. Publish/release the capsule version you need, then pin that version in the distro.
  3. If you genuinely need a git-ref build, install it via `astrid capsule install` outside the distro manifest.

Example fix

# before
[[capsules]]
name = "http"
branch = "main"

# after
[[capsules]]
name = "http"
version = "1.4.2"
Defensive patterns

Strategy: validation

Validate before calling

for cap in &manifest.capsules {
    if cap.branch.is_some() || cap.rev.is_some() {
        panic!("capsule '{}' uses branch/rev; pin a version or tag", cap.name);
    }
}

Try / catch

if let Err(e) = validate_manifest(&manifest) {
    if e.to_string().contains("branch/rev require building from source") {
        eprintln!("pin a release instead: {e}");
    }
}

Prevention

When it happens

Trigger: A `[[capsules]]` entry in a distro manifest with `branch = "main"` and/or `rev = "abc123"` set (either one triggers the bail).

Common situations: Copying a capsule-install invocation's git-ref fields into a distro manifest; wanting an unreleased fix in a distro; migrating a dev manifest into a distro manifest without pinning a release.

Related errors


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