astrid-runtime/astrid · error

legacy capsule metadata has no WASM hash

Error message

legacy capsule metadata has no WASM hash

What it means

During legacy migration, the component's WASM hash from the legacy metadata is used to locate the binary at home.bin_dir()/<hash>.wasm. If meta.wasm_hash is missing (None), the migration cannot locate or hash-verify the component and canonical_legacy_archive bails with this error.

Source

Thrown at crates/astrid-capsule-install/src/storage.rs:655

    meta: &CapsuleMeta,
    manifest: &astrid_capsule::manifest::CapsuleManifest,
) -> anyhow::Result<Vec<u8>> {
    let staging = tempfile::tempdir().context("stage legacy capsule for migration")?;
    copy_legacy_tree(target, staging.path())?;
    if let Some(component) = manifest.components.first() {
        let component_path = component.path.clone();
        if component_path.is_absolute()
            || component_path.components().any(|part| {
                matches!(
                    part,
                    std::path::Component::ParentDir | std::path::Component::RootDir
                )
            })
        {
            bail!("legacy capsule component path is not relative");
        }
        let Some(hash) = meta.wasm_hash.as_deref() else {
            bail!("legacy capsule metadata has no WASM hash");
        };
        let wasm = home.bin_dir().join(format!("{hash}.wasm"));
        let destination = staging.path().join(component_path);
        if let Some(parent) = destination.parent() {
            fs::create_dir_all(parent)?;
        }
        fs::copy(&wasm, &destination).with_context(|| {
            format!("restore content-addressed WASM blob for {}", wasm.display())
        })?;
    }
    for (relative, hash) in &meta.wit_files {
        let relative = Path::new(relative);
        if relative.is_absolute()
            || relative.components().any(|part| {
                matches!(
                    part,
                    std::path::Component::ParentDir | std::path::Component::RootDir
                )

View on GitHub (pinned to affd8760f4)

Solutions

  1. Compute the WASM hash (e.g. SHA-256 of the component .wasm) and add wasm_hash to the legacy meta file.
  2. Reinstall the legacy capsule with a tool version that records wasm_hash, then rerun migration.
  3. Delete the broken legacy capsule so migration can skip it or reinstall it cleanly.

Example fix

// before (legacy meta.toml)
name = "foo"
# wasm_hash missing
// after
name = "foo"
wasm_hash = "<sha256 of foo.wasm>"
Defensive patterns

Strategy: validation

Validate before calling

match meta.wasm_hash.as_deref() {
    Some(h) if !h.is_empty() => { /* ok */ }
    _ => anyhow::bail!("legacy capsule {} has no wasm_hash; recompute before migrating", meta.name),
}

Try / catch

match migrate_native_capsules_with_report(&home) {
    Err(e) if e.to_string().contains("no WASM hash") => {
        warn!("legacy capsule missing wasm_hash; recomputing hashes");
        recompute_legacy_wasm_hashes(&home)?;
        migrate_native_capsules_with_report(&home)?;
    }
    other => other,
}

Prevention

When it happens

Trigger: migrate_native_capsules_with_report encounters a legacy capsule whose meta file lacks the wasm_hash field — the field is absent, null, or an empty string filtered to None.

Common situations: Very old legacy capsules installed before wasm_hash was recorded; a hand-edited or truncated meta file; a partially-failed legacy install that wrote metadata without the hash.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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