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

  1. Reinstall or rebuild the offending capsule so meta.json's wit_files contains a key whose basename is exactly `astrid-contracts.wit`.
  2. Inspect the capsule's meta.json wit_files keys and correct the entry basename to astrid-contracts.wit.
  3. 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

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


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