astrid-runtime/astrid · error
signed Distro.lock contains undeclared capsule
Error message
signed Distro.lock contains undeclared capsule '{}' What it means
While walking the signed Distro.lock, every lock entry must correspond to a capsule declared in Distro.toml. If a lock capsule's name has no declared counterpart, the lock references something the signed manifest never authorized — a supply-chain red flag — so validation aborts with this message naming the offending capsule.
Solutions
- Regenerate and re-sign Distro.lock from the current Distro.toml so both member sets match
- If the capsule should still exist, re-add its declaration to Distro.toml and re-seal
- Remove the stale capsule entry from Distro.lock and republish
Example fix
# before: lock has 'legacy' but toml doesn't capsules = ["alpha", "legacy"] # lock capsules = ["alpha"] # toml # after: regenerate lock capsules = ["alpha"] # lock (regenerated & re-signed)
Defensive patterns
Strategy: validation
Validate before calling
let declared: HashSet<&str> = manifest.capsules.iter().map(|c| c.name.as_str()).collect();
let extra: Vec<_> = lock.capsules.iter().map(|c| c.name.as_str()).filter(|n| !declared.contains(n)).collect();
if !extra.is_empty() { eprintln!("lock has undeclared capsules: {extra:?}"); } Try / catch
match validate_signed_member_sets(manifest, lock) {
Err(e) if e.to_string().contains("undeclared capsule") => {
eprintln!("Lock references a capsule removed from Distro.toml; regenerate + re-seal the lock");
}
r => r?,
} Prevention
- Treat Distro.lock as generated output only — always rebuild after TOML edits
- Re-seal and republish manifest+lock atomically
- Verify lock/manifest pair freshness before consuming a distro
When it happens
Trigger: fetch_signed_manifest -> verify_signed_manifest -> validate_signed_member_sets when Distro.lock contains a capsule name that Distro.toml does not declare (e.g. lock left over from a removed capsule, or a tampered lock).
Common situations: A capsule was deleted from Distro.toml but Distro.lock was not regenerated before re-sealing/publishing; restoring an old lock file over a newer manifest; manual lock editing.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- signed Distro.lock members do not match Distro.toml…
- astrid distro apply requires a signed Distro…
- capsule archive already contains
- capsule archive contains duplicate entry
- capsule disappeared during durable contracts scan
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/b91a603a03ec67c3.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-cli/src/commands/init_signed_source.rs:354
{
bail!("Distro.lock identity does not match the signed Distro.toml");
}
let declared: HashMap<&str, &DistroCapsule> = manifest
.capsules
.iter()
.map(|capsule| (capsule.name.as_str(), capsule))
.collect();
anyhow::ensure!(
declared.len() == manifest.capsules.len() && lock.capsules.len() == declared.len(),
"signed Distro.lock members do not match Distro.toml declarations"
);
for capsule in &lock.capsules {
let declared_capsule = declared
.get(capsule.name.as_str())
.copied()
.ok_or_else(|| {
anyhow::anyhow!(
"signed Distro.lock contains undeclared capsule '{}'",
capsule.name
)
})?;
if capsule.source != declared_capsule.source || capsule.version != declared_capsule.version
{
bail!(
"signed Distro.lock entry '{}' does not match Distro.toml",
capsule.name
);
}
anyhow::ensure!(
!capsule.hash.is_empty(),
"signed Distro.lock entry '{}' has no capsule hash",
capsule.name
);
}
Ok(())View on GitHub (pinned to affd8760f4)