astrid-runtime/astrid · error
durable capsule {id} metadata names a hash for a non-WASM co
Error message
durable capsule {id} metadata names a hash for a non-WASM component What it means
verify_package_identity found metadata.wasm_hash set while the capsule's component file does not have a .wasm extension, so there is no WASM artifact the recorded hash could describe. The library rejects this because wasm_hash is only meaningful for a WASM component; a populated value next to a non-WASM component indicates inconsistent metadata. Read of the verified durable package is refused.
Source
Thrown at crates/astrid-capsule-install/src/storage.rs:315
};
let Some(bytes) = archive_files.get(relative) else {
bail!("durable capsule {id} component is missing from its archive");
};
if Path::new(relative)
.extension()
.is_some_and(|extension| extension.eq_ignore_ascii_case("wasm"))
{
let archive_hash = blake3::hash(bytes).to_hex().to_string();
if authority.wasm_hash_pinned
&& authority.approved_wasm_hash.as_deref() != Some(archive_hash.as_str())
{
bail!("durable capsule {id} WASM hash differs between authority and archive");
}
if metadata.wasm_hash.as_deref() != Some(archive_hash.as_str()) {
bail!("durable capsule {id} WASM hash differs between metadata and archive");
}
} else if metadata.wasm_hash.is_some() {
bail!("durable capsule {id} metadata names a hash for a non-WASM component");
}
} else if metadata.wasm_hash.is_some() {
bail!("durable capsule {id} metadata names a component absent from its archive");
}
let mut effective_capabilities = manifest.capabilities.clone();
for component in &manifest.components {
if let Some(capabilities) = &component.capabilities {
effective_capabilities.merge_from(capabilities);
}
}
if !effective_capabilities
.expansions_from(&authority.approved_capabilities)
.is_empty()
{
bail!("durable capsule {id} manifest exceeds its authority receipt");
}
match verification {
ArtifactVerification::Signed(provenance) => {View on GitHub (pinned to affd8760f4)
Solutions
- Clear metadata.wasm_hash (set to None) for capsules whose component is not a .wasm file.
- Restore the .wasm component if the capsule was actually meant to ship WASM.
- Fix the publishing tool so it only sets wasm_hash when the component path ends in .wasm.
- Republish the capsule with consistent manifest + metadata.
Example fix
// before
meta.wasm_hash = Some(hash_of_nonwasm_component);
// after
if component.path.extension().is_some_and(|e| e.eq_ignore_ascii_case("wasm")) {
meta.wasm_hash = Some(hash);
} else {
meta.wasm_hash = None;
} Defensive patterns
Strategy: validation
Validate before calling
if meta.wasm_hash.is_some()
&& !component.path.extension().is_some_and(|e| e.eq_ignore_ascii_case("wasm"))
{
return Err("wasm_hash set but component is not a .wasm file");
} Type guard
fn is_wasm_component(p: &std::path::Path) -> bool {
p.extension().is_some_and(|e| e.eq_ignore_ascii_case("wasm"))
} Try / catch
match read_verified_durable_package_for_owner(&store, owner, id).await {
Ok(pkg) => pkg,
Err(e) if e.to_string().contains("hash for a non-WASM component") => {
// clear metadata.wasm_hash or restore the wasm component
},
Err(e) => return Err(e),
} Prevention
- Set wasm_hash only when the component path ends in .wasm.
- Regenerate metadata whenever the component type changes.
- Add a pre-publish check that mirrors verify_package_identity's rules.
When it happens
Trigger: read_verified_durable_package_for_owner on a capsule whose manifest component path lacks a .wasm extension (or component.path isn't UTF-8-safe with .wasm) while CapsuleMeta.wasm_hash is Some(_).
Common situations: Metadata written for an earlier WASM build that was later replaced by a non-WASM component (e.g. a WIT-only or data component); copy-pasting metadata between capsules; a tool that unconditionally stamps wasm_hash.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- durable capsule {id} metadata names a component absent from
- Distro.lock capsule '{capsule}' declares WASM but has no ins
- volume metadata transaction must contain 1 to 1024 mutations
- metadata region name too long
- 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/358c2ccd128780f1.
Report an issue: GitHub.