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
- Refresh the distro/lock data so the signed ref matches the currently published ref, then rerun the install.
- Inspect the installer log to see which ref was actually resolved; if it is the legitimate new ref, update the signed ref expectation.
- Verify the capsule source repository for force-pushes or tag moves before trusting either ref.
- 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
- Pin immutable commit hashes rather than movable tags/branches.
- Verify upstream repos for force-pushes before trusting signed refs.
- Refresh distro lock/signed refs through a verified update flow.
- Alert on signed-ref mismatch instead of silently re-resolving.
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
- capsule ' ' release selector declared version , but the…
- capsule ' ' hash mismatch: signed lock has , resolved…
- capsule identity mismatch: expected
- capsule identity mismatch: expected
- capsule ' ' is ; explicit local approval is required
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)