astrid-runtime/astrid · error
durable capsule {} is missing its pinned contracts blob
Error message
durable capsule {} is missing its pinned contracts blob What it means
After validating the pin, durable_contracts_pin looks up the relative path of the astrid-contracts.wit entry whose basename matches the pin key. If no entry's basename matches CONTRACTS_WIT_BASENAME, the capsule is considered internally inconsistent — it claims to pin contracts (contracts_pin returned Some) but the code cannot find the matching relative path — so the scan fails fast instead of skipping the capsule.
Source
Thrown at crates/astrid-capsule-install/src/contracts.rs:117
if !is_blake3_pin(pin) {
bail!(
"durable capsule {} has malformed contracts pin",
summary.id()
);
}
let Some(relative) = package
.metadata()
.wit_files
.keys()
.filter(|relative| {
Path::new(relative.as_str())
.file_name()
.and_then(|name| name.to_str())
== Some(CONTRACTS_WIT_BASENAME)
})
.min()
else {
bail!(
"durable capsule {} is missing its pinned contracts blob",
summary.id()
);
};
let Some(blob) = package.wit_file(relative) else {
bail!(
"durable capsule {} is missing its pinned contracts blob",
summary.id()
);
};
if blake3::hash(blob).to_hex().as_str() != pin {
bail!(
"durable capsule {} contracts blob digest mismatch",
summary.id()
);
}
let count = counts.entry(pin.clone()).or_default();
*count = count.saturating_add(1);View on GitHub (pinned to affd8760f4)
Solutions
- Reinstall or rebuild the offending capsule so meta.json's wit_files contains a key whose basename is exactly `astrid-contracts.wit`.
- Inspect the capsule's meta.json wit_files keys and correct the entry basename to astrid-contracts.wit.
- Re-publish the durable package if its metadata cannot be repaired in place.
Example fix
// before (meta.json wit_files key) "deps/astrid-contracts/contracts.wit": "<blake3 hex>" // after "deps/astrid-contracts/astrid-contracts.wit": "<blake3 hex>"
Defensive patterns
Strategy: validation
Validate before calling
// pre-check before scanning:
let pin_key = package.metadata().wit_files.keys()
.find(|k| Path::new(k).file_name().and_then(|n| n.to_str()) == Some("astrid-contracts.wit"));
assert!(pin_key.is_some(), "capsule lacks astrid-contracts.wit entry"); Type guard
fn has_contracts_entry(wit_files: &HashMap<String, String>) -> bool {
wit_files.keys().any(|k| Path::new(k).file_name().and_then(|n| n.to_str()) == Some("astrid-contracts.wit"))
} Prevention
- Keep wit_files keys' basenames exactly `astrid-contracts.wit` when packaging.
- Use the SDK packager instead of custom metadata writers.
- Validate archives after publish with the packaging tool's verify step.
When it happens
Trigger: Calling durable_contracts_pin / refresh_canonical_contracts_from_registry when a capsule's meta.json has an astrid-contracts.wit pin entry, yet the filter over wit_files keys (matching on Path::file_name == astrid-contracts.wit) unexpectedly yields no key — e.g. a non-UTF8 or unusual path encoding case that dodges the first lookup — an internal-inconsistency state reached when contracts_pin succeeds but the second key enumeration fails.
Common situations: meta.json whose wit_files keys were rewritten with different casing or extensions; a buggy custom packager writing pin entries without matching key paths.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- durable capsule {id} imports differ between metadata and arc
- durable capsule {id} is missing WIT file {relative}
- durable capsule {id} WIT digest mismatch for {relative}
- durable capsule {id} has an unpinned WIT file {key}
- installed capsule identity/version differs from its authorit
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/fb59569c3948b559.
Report an issue: GitHub.