astrid-runtime/astrid · error

installed WASM integrity check failed: expected BLAKE3 {expe

Error message

installed WASM integrity check failed: expected BLAKE3 {expected}, got {actual}

What it means

Integrity assertion in catalog_wasm_hash: after reading the installed WASM back from the system catalog, its BLAKE3 digest does not equal the expected content-addressed hash. This means the bytes stored under bin/{expected}.wasm are not the bytes the name promises — corruption or substitution of installed WASM.

Source

Thrown at crates/astrid-capsule-install/src/wasm.rs:135

        .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)
}

#[cfg(test)]
mod tests {
    use super::*;
    use astrid_capsule::discovery::load_manifest;
    use astrid_storage::{KvQuotaResolver, open_runtime_principal_store};
    use std::sync::Arc;

    fn unlimited_quota() -> Arc<dyn KvQuotaResolver<StateOwner>> {
        Arc::new(|owner: &StateOwner| {
            Ok(match owner {
                StateOwner::System => None,
                StateOwner::Principal(_) | StateOwner::Fleet(_) => Some(u64::MAX),

View on GitHub (pinned to affd8760f4)

Solutions

  1. Re-install the WASM so the catalog entry is republished from the trusted source and the hash matches
  2. Compare the actual hash against the source artifact's BLAKE3 to determine if the store corrupted the bytes or the expected hash is wrong
  3. Check for external processes (AV, sync tools) modifying files inside the content store
  4. Confirm hash string casing/format matches (hex, no 0x prefix) on both sides

Example fix

// before
anyhow::ensure!(actual == expected, "installed WASM integrity check failed: expected BLAKE3 {expected}, got {actual}");
// after: recover by republishing instead of hard-failing
if actual != expected {
    republish_wasm(storage, expected_bytes)?; // rewrite catalog entry from trusted source
}
anyhow::ensure!(actual == expected, "installed WASM integrity check failed: expected BLAKE3 {expected}, got {actual}");
Defensive patterns

Strategy: try-catch

Validate before calling

// verify before trusting the installed capsule
let actual = blake3::hash(&read_catalog_wasm(&storage, &expected)?).to_hex().to_string();
if actual != expected {
    eprintln!("installed WASM corrupted; republishing from source");
    republish_wasm(&storage, &source_bytes)?;
}

Try / catch

match catalog_wasm_hash(&storage, &expected) {
    Ok(actual) => actual,
    Err(e) if e.to_string().contains("integrity check failed") => {
        republish_wasm(&storage, &source_bytes)?; // self-heal from trusted source
        catalog_wasm_hash(&storage, &expected)?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: catalog_wasm_hash(storage, expected) is called; read_catalog_wasm succeeds, blake3::hash of the bytes differs from `expected`, and anyhow::ensure! fires.

Common situations: Disk corruption or bit-rot in the content store; a process rewrote the catalog entry with different bytes under the same name; artifact modified after install (antivirus/quarantine rewrite); comparing a hash computed with a different algorithm/version against stored content; stale entry from a previous build published under a reused name.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


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