astrid-runtime/astrid · error

durable contracts blob disappeared

Error message

durable contracts blob disappeared

What it means

refresh_canonical_contracts_from_registry re-resolves the durable contracts WIT blob from installed packages; if every candidate package lookup returns None the blob variable stays None and the function throws 'durable contracts blob disappeared', an internal invariant failure meaning the registry no longer holds content that was expected to exist.

Solutions

  1. Reinstall the capsule package that provides the durable contracts WIT
  2. Re-run the install/refresh so the registry repopulates the package set
  3. Clear stale install state and perform a fresh install
  4. Report as a bug if the package is present but lookup still fails (invariant violation)
Defensive patterns

Strategy: retry

Validate before calling

fn canonical_blob_present(home: &Path) -> bool {
    std::fs::read(canonical_contracts_path(home)).is_ok()
}

Try / catch

match refresh_canonical_contracts_from_registry(...) {
    Err(e) if e.to_string().contains("durable contracts blob disappeared") => {
        eprintln!("contracts package missing; reinstall and retry refresh");
        // reinstall_package(); retry once
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling refresh_canonical_contracts_from_registry when the wit_file(relative) lookups over the installed packages all fail — e.g. the package providing the contracts WIT was uninstalled, upgraded, or its internal layout changed between resolution and refresh.

Common situations: Concurrent install/uninstall racing the refresh; partial upgrade that removed the old package before writing the new canonical blob; corrupted capsule-install state directory.

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/23b95d0ff5d4c809. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-capsule-install/src/contracts.rs:192

            .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 {
            continue;
        };
        blob = package.wit_file(relative).map(ToOwned::to_owned);
        if blob.is_some() {
            break;
        }
    }
    let content = blob.ok_or_else(|| anyhow::anyhow!("durable contracts blob disappeared"))?;
    let canonical = canonical_contracts_path(home);
    if std::fs::read(&canonical).is_ok_and(|existing| existing == content) {
        return Ok(());
    }
    write_canonical_atomic(&canonical, &content)
        .with_context(|| format!("failed to write canonical {}", canonical.display()))
}

/// BLAKE3 hex of the daemon canonical `astrid-contracts.wit`, or `None`
/// when the canonical file is absent or unreadable.
/// Absent canonical is a normal state (fresh home, daemon never booted) —
/// the caller degrades silently rather than treating it as an error.
#[must_use]
pub fn canonical_contracts_b3(home: &AstridHome) -> Option<String> {
    let bytes = std::fs::read(canonical_contracts_path(home)).ok()?;
    Some(blake3::hash(&bytes).to_hex().to_string())
}

View on GitHub (pinned to affd8760f4)