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
- Compute the WASM hash (e.g. SHA-256 of the component .wasm) and add wasm_hash to the legacy meta file.
- Reinstall the legacy capsule with a tool version that records wasm_hash, then rerun migration.
- 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
- Verify every legacy meta has a non-empty wasm_hash before starting migration.
- Recompute hashes from the .wasm files when metadata is missing or suspect.
- Keep legacy installs created by tooling that always records wasm_hash; skip and report capsules that predate it.
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
- legacy capsule component path is not relative
- legacy capsule metadata version differs for {id}
- legacy capsule {id} metadata changed before retirement
- WASM capsule has no BLAKE3 hash in meta.json
- durable capsule {id} imports differ between metadata and arc
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/899e5c356a3c51b2.
Report an issue: GitHub.