astrid-runtime/astrid · error

release of / ships no .capsule asset — seal requires…

Error message

release {resolved_ref} of {org}/{repo} ships no .capsule asset — seal requires pre-built release artifacts

What it means

This error is thrown by `resolve_capsule_to_file` in astrid-cli when a GitHub release of a capsule repository contains no `.capsule` asset. Capsule installation from GitHub releases only consumes pre-built release artifacts; `capsule_assets(assets)` filters the release asset list and `pick_capsule` selects a matching one, and if no candidate survives the filter, installation cannot proceed. The library deliberately does not fall back to building from source in this path.

Solutions

  1. Check the release page for {org}/{repo} at the resolved ref and confirm a `.capsule` asset exists; pick a different tag/ref that has one
  2. Upgrade or change the requested ref to a release where CI successfully uploaded the `.capsule` artifact
  3. Re-run the project's release pipeline (or manually attach the built `.capsule` file to the release) so the asset exists
  4. Use the from-source installation path (`clone_and_build` via install from GitHub source mode) which clones and runs `astrid-build` instead of consuming release assets

Example fix

// before: installing a tag with no pre-built asset
astrid capsule install github:org/repo@v0.1.0
// after: use a release that ships .capsule artifacts, or build from source
astrid capsule install github:org/repo@v0.2.1
Defensive patterns

Strategy: validation

Validate before calling

// Check the release has a .capsule asset before installing
let assets = fetch_release_assets(org, repo, resolved_ref)?;
let has_capsule = capsule_assets(&assets).len() > 0;
if !has_capsule {
    eprintln!("release {resolved_ref} of {org}/{repo} has no .capsule asset; pick another ref or build from source");
}

Try / catch

match resolve_capsule_to_file(...) {
    Ok(path) => proceed(path),
    Err(e) if e.to_string().contains("ships no .capsule asset") => {
        // fall back to source build path or prompt user for another ref
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling capsule install from GitHub with a source-repo/release path where the resolved release (tag, branch, or latest) has zero assets matching the `.capsule` pattern — e.g. the maintainer published a release with only source archives (Source code zip/tar.gz) and no pre-built `.capsule` file, or the asset has a different extension.

Common situations: Developer pins an older release tag from before the project started attaching `.capsule` artifacts; a CI pipeline failed to upload the built capsule asset; the repo ships releases for a different artifact convention; a typo'd ref resolves to a release without assets.

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


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

Appendix: source

Thrown at crates/astrid-cli/src/commands/capsule/install.rs:457

        .send()
        .await
        .context("failed to fetch release metadata")?;
    if !response.status().is_success() {
        bail!(
            "GitHub API returned {} fetching release {resolved_ref} of {org}/{repo}",
            response.status()
        );
    }
    let json: serde_json::Value = response.json().await.context("invalid release metadata")?;
    let assets = json
        .get("assets")
        .and_then(serde_json::Value::as_array)
        .map(Vec::as_slice)
        .unwrap_or_default();
    let candidates = capsule_assets(assets);
    let names: Vec<&str> = candidates.iter().map(|(n, _)| n.as_str()).collect();
    let Some(idx) = pick_capsule(&names, name_hint)? else {
        bail!(
            "release {resolved_ref} of {org}/{repo} ships no .capsule asset — \
             seal requires pre-built release artifacts"
        );
    };
    let (_, download_url) = &candidates[idx];

    download_capsule_asset(&client, download_url, dest_path).await?;
    Ok(resolved_ref)
}

/// Download a single `.capsule` asset (streamed, 50 MB cap) and install it.
/// Returns the installed capsule id.
async fn download_and_unpack(
    client: &reqwest::Client,
    name: &str,
    download_url: &str,
    context: InstallContext<'_>,
) -> anyhow::Result<InstalledCapsuleOutcome> {

View on GitHub (pinned to affd8760f4)