{"record":{"id":"23b95d0ff5d4c809","repo":"astrid-runtime/astrid","slug":"durable-contracts-blob-disappeared","errorCode":null,"errorMessage":"durable contracts blob disappeared","messagePattern":"durable contracts blob disappeared","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-capsule-install/src/contracts.rs","lineNumber":192,"sourceCode":"            .metadata()\n            .wit_files\n            .keys()\n            .filter(|relative| {\n                Path::new(relative.as_str())\n                    .file_name()\n                    .and_then(|name| name.to_str())\n                    == Some(CONTRACTS_WIT_BASENAME)\n            })\n            .min()\n        else {\n            continue;\n        };\n        blob = package.wit_file(relative).map(ToOwned::to_owned);\n        if blob.is_some() {\n            break;\n        }\n    }\n    let content = blob.ok_or_else(|| anyhow::anyhow!(\"durable contracts blob disappeared\"))?;\n    let canonical = canonical_contracts_path(home);\n    if std::fs::read(&canonical).is_ok_and(|existing| existing == content) {\n        return Ok(());\n    }\n    write_canonical_atomic(&canonical, &content)\n        .with_context(|| format!(\"failed to write canonical {}\", canonical.display()))\n}\n\n/// BLAKE3 hex of the daemon canonical `astrid-contracts.wit`, or `None`\n/// when the canonical file is absent or unreadable.\n/// Absent canonical is a normal state (fresh home, daemon never booted) —\n/// the caller degrades silently rather than treating it as an error.\n#[must_use]\npub fn canonical_contracts_b3(home: &AstridHome) -> Option<String> {\n    let bytes = std::fs::read(canonical_contracts_path(home)).ok()?;\n    Some(blake3::hash(&bytes).to_hex().to_string())\n}\n","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-capsule-install/src/contracts.rs#L174-L210","documentation":"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.","triggerScenarios":"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.","commonSituations":"Concurrent install/uninstall racing the refresh; partial upgrade that removed the old package before writing the new canonical blob; corrupted capsule-install state directory.","solutions":["Reinstall the capsule package that provides the durable contracts WIT","Re-run the install/refresh so the registry repopulates the package set","Clear stale install state and perform a fresh install","Report as a bug if the package is present but lookup still fails (invariant violation)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"fn canonical_blob_present(home: &Path) -> bool {\n    std::fs::read(canonical_contracts_path(home)).is_ok()\n}","typeGuard":null,"tryCatchPattern":"match refresh_canonical_contracts_from_registry(...) {\n    Err(e) if e.to_string().contains(\"durable contracts blob disappeared\") => {\n        eprintln!(\"contracts package missing; reinstall and retry refresh\");\n        // reinstall_package(); retry once\n    }\n    other => other?,\n}","preventionTips":["Avoid concurrent installs/uninstalls while a refresh is running","Keep the contracts-providing package installed before lifecycle refreshes","Verify install state after upgrades before triggering refresh"],"tags":["contracts","install","internal","registry"],"backgroundTag":"internal-invariant-violation","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}