astrid-runtime/astrid · error
read WASM from system catalog
Error message
read WASM from system catalog
What it means
Wraps a storage error from content().read_range() when reading back the full byte range of a WASM catalog entry after a successful describe(). The descriptor exists but actually reading the bytes failed, so catalog_wasm_hash cannot compute the integrity digest.
Source
Thrown at crates/astrid-capsule-install/src/wasm.rs:121
}
/// Read one verified executable from the system-owned content catalog.
pub(crate) fn read_catalog_wasm(
storage: &RuntimePrincipalStore,
hash: &str,
) -> anyhow::Result<Vec<u8>> {
let name = ContentName::new(format!("bin/{hash}.wasm"))
.context("construct system WASM catalog name")?;
let descriptor = storage
.content()
.describe(&StateOwner::System, &name)
.map_err(|error| anyhow::anyhow!(error))
.context("describe WASM in system catalog")?
.ok_or_else(|| anyhow::anyhow!("WASM catalog entry is missing: bin/{hash}.wasm"))?;
storage
.content()
.read_range(&StateOwner::System, &name, 0, descriptor.logical_bytes())
.map_err(|error| anyhow::anyhow!(error))
.context("read WASM from system catalog")?
.ok_or_else(|| anyhow::anyhow!("WASM catalog entry has no readable bytes: bin/{hash}.wasm"))
}
/// Verify that the system catalog entry for `expected` exists and hashes to
/// its content-addressed name.
pub fn catalog_wasm_hash(
storage: &RuntimePrincipalStore,
expected: &str,
) -> anyhow::Result<String> {
let actual = blake3::hash(&read_catalog_wasm(storage, expected)?)
.to_hex()
.to_string();
anyhow::ensure!(
actual == expected,
"installed WASM integrity check failed: expected BLAKE3 {expected}, got {actual}"
);
Ok(actual)View on GitHub (pinned to affd8760f4)
Solutions
- Re-publish the WASM into the catalog (re-run the install) to rewrite the missing/truncated blob
- Inspect the wrapped storage error for the concrete filesystem/backend cause
- Check the content store for orphaned descriptors and prune or repair them
- Verify no concurrent GC/compaction is running while reads are in flight
Defensive patterns
Strategy: retry
Validate before calling
// sanity: descriptor and blob must both be readable
let d = storage.content().describe(&StateOwner::System, &name)?.ok_or("missing")?;
storage.content().read_range(&StateOwner::System, &name, 0, d.logical_bytes())?
.ok_or("blob unreadable")?; Try / catch
match catalog_wasm_hash(&storage, &expected) {
Err(e) if e.to_string().contains("read WASM from system catalog") => {
// blob missing/truncated: republish and re-verify once
republish_wasm(&storage, &source_bytes)?;
catalog_wasm_hash(&storage, &expected)
}
other => other,
} Prevention
- Avoid interrupting installs mid-ingest; interrupted writes leave descriptors without blobs
- Keep GC/compaction from running concurrently with catalog reads
- Monitor the content store for orphaned descriptors
When it happens
Trigger: catalog_wasm_hash -> read_catalog_wasm: describe(&StateOwner::System, name) returns Some(descriptor), then read_range(&StateOwner::System, &name, 0, descriptor.logical_bytes()) returns Err.
Common situations: Underlying blob file deleted or truncated while the descriptor still exists (partial GC, interrupted write); filesystem read/permission errors; corrupt content-store index pointing at a missing chunk; descriptor reporting logical_bytes beyond what is physically stored.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- publish WASM into the system content catalog
- describe WASM in system catalog
- WASM catalog entry is missing: bin/{hash}.wasm
- WASM catalog entry has no readable bytes: bin/{hash}.wasm
- WASM capsule has no BLAKE3 hash in meta.json
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/89188e120e3a1876.
Report an issue: GitHub.