astrid-runtime/astrid · error

Distro.lock non-WASM capsule '{capsule}' must not carry a WA

Error message

Distro.lock non-WASM capsule '{capsule}' must not carry a WASM hash

What it means

Fired by validate_locked_wasm when a Distro.lock entry for a capsule whose manifest declares no WASM still carries a locked WASM hash. The lockfile asserts a hash for a component the manifest says has no WASM, which is an inconsistent lock state.

Source

Thrown at crates/astrid-cli/src/commands/init_grant.rs:367

        },
    }
}

fn validate_locked_wasm(
    home: &AstridHome,
    capsule: &CapsuleId,
    manifest: &CapsuleManifest,
    meta_hash: Option<&str>,
    locked_hash: &str,
    store: Option<&astrid_storage::RuntimePrincipalStore>,
) -> anyhow::Result<()> {
    let declares_wasm = manifest_declares_wasm(manifest);
    let Some(meta_hash) = meta_hash else {
        if declares_wasm {
            bail!("Distro.lock capsule '{capsule}' declares WASM but has no installed WASM hash");
        }
        if !locked_hash.is_empty() {
            bail!("Distro.lock non-WASM capsule '{capsule}' must not carry a WASM hash");
        }
        return Ok(());
    };

    if !declares_wasm {
        bail!(
            "Distro.lock capsule '{capsule}' does not declare WASM but installed metadata carries a WASM hash"
        );
    }
    let locked = parse_locked_blake3(capsule, locked_hash)?;
    let locked_hex = locked.to_hex().to_string();
    if meta_hash != locked_hex {
        bail!("Distro.lock capsule '{capsule}' hash disagrees with installed metadata");
    }
    let bytes = if let Some(store) = store {
        let name = astrid_storage::ContentName::new(format!("bin/{locked_hex}.wasm"))?;
        let descriptor = store
            .content()

View on GitHub (pinned to affd8760f4)

Solutions

  1. Remove the hash field for that capsule from Distro.lock (or regenerate the lockfile).
  2. Restore the WASM declaration in the capsule manifest if the capsule does ship WASM.
  3. Regenerate Distro.lock from the current manifests so hashes and declarations agree.

Example fix

// before (Distro.lock)
{ name = "tools", wasm_hash = "blake3:..." }
// after
{ name = "tools" }
Defensive patterns

Strategy: validation

Validate before calling

if !manifest_declares_wasm(&manifest) && !locked_hash.is_empty() {
    return Err(anyhow!("{} must not carry a wasm hash", capsule));
}

Try / catch

if let Err(e) = validate_lock(&lock) {
    if e.to_string().contains("must not carry a WASM hash") {
        regenerate_lockfile().await?;
    } else { return Err(e.into()); }
}

Prevention

When it happens

Trigger: validate_locked_wasm receives declares_wasm == false and a non-empty locked_hash string for the capsule.

Common situations: Hand-edited Distro.lock adding a hash to a non-WASM capsule, lockfile generated by an older tool version with different manifest semantics, or manifest rewritten to drop the wasm declaration after the lock was written.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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