astrid-runtime/astrid · error

capsule ' ' signed ref did not match installed ref

Error message

capsule '{expected}' signed ref {expected_ref} did not match installed ref {:?}

What it means

After a batch install, validate_batch_install checks that the resolved git ref recorded by the installer matches the signed ref the distro expected. If outcome.resolved_ref differs from expected_ref, it bails. This ensures the capsule was installed from the exact signed commit/ref, protecting supply-chain integrity.

Solutions

  1. Refresh the distro/lock data so the signed ref matches the currently published ref, then rerun the install.
  2. Inspect the installer log to see which ref was actually resolved; if it is the legitimate new ref, update the signed ref expectation.
  3. Verify the capsule source repository for force-pushes or tag moves before trusting either ref.
  4. Pin to a commit hash instead of a mutable ref to avoid drift.

Example fix

// before
expected_ref = "refs/tags/v1.0.0"   // upstream moved tag to a new commit
// after
expected_ref = "refs/tags/v1.0.1"   // refreshed signed ref after verifying upstream
Defensive patterns

Strategy: validation

Validate before calling

if let Some(expected_ref) = expected_ref {
    let resolved = fetch_resolved_ref(capsule)?; // before install
    if resolved.as_deref() != Some(expected_ref) {
        return Err(anyhow!("signed ref drift for {capsule}: {resolved:?} != {expected_ref}"));
    }
}

Try / catch

match result {
    Err(e) if e.to_string().contains("signed ref") => eprintln!("upstream ref moved; refresh signed ref after verifying"),
    Err(e) => return Err(e),
    Ok(v) => Ok(v),
}

Prevention

When it happens

Trigger: install_capsules_with_resume passes an expected_ref (signed ref from the distro) and the install outcome's resolved_ref is None or points to a different ref/commit.

Common situations: The upstream repository was force-pushed or the signed ref was rotated; a mirror checked out a different branch/commit; the distro lockfile is stale relative to the published signed ref.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at crates/astrid-cli/src/commands/init.rs:875

        .into_iter()
        .next()
        .expect("length checked");
    if installed.id != *expected {
        bail!(
            "distro declared capsule '{expected}', but the checked installer reported '{}'",
            installed.id
        );
    }
    if !declared_version.is_empty() && installed.version != declared_version {
        bail!(
            "capsule '{expected}' release selector declared version {declared_version}, but the installed manifest reports {}",
            installed.version
        );
    }
    if let Some(expected_ref) = expected_ref
        && outcome.resolved_ref.as_deref() != Some(expected_ref)
    {
        bail!(
            "capsule '{expected}' signed ref {expected_ref} did not match installed ref {:?}",
            outcome.resolved_ref
        );
    }
    Ok(VerifiedBatchInstall {
        version: installed.version,
        wasm_hash: installed.wasm_hash,
        resolved_ref: outcome.resolved_ref,
        skipped: installed.skipped,
    })
}

/// Persist distro variable templates through the daemon's typed env API.
///
/// Init may run before a capsule has been installed, so this deliberately
/// does not require a capsule manifest to classify fields. Variable metadata
/// from `Distro.toml` carries the secret bit; unresolved literal fields are
/// ordinary text. The daemon remains the only writer for durable env state.

View on GitHub (pinned to affd8760f4)