astrid-runtime/astrid · error

durable capsule {id} metadata names a component absent from

Error message

durable capsule {id} metadata names a component absent from its archive

What it means

The manifest has no components at all, yet metadata.wasm_hash is Some. The library throws this because a hash naming an executable implies an executable component exists; with an empty component list the metadata references something that cannot exist in the archive. Verification of the durable package fails before it is served.

Source

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

        };
        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) => {
            let signer = provenance.signer.to_string();
            let signature = provenance.signature.to_string();
            if authority.signer.as_deref() != Some(signer.as_str())

View on GitHub (pinned to affd8760f4)

Solutions

  1. Add the WASM component back to the manifest/archive and republish.
  2. Set metadata.wasm_hash to None if the capsule is intentionally component-free.
  3. Regenerate both manifest and metadata from the same source tree so they cannot diverge.
  4. Inspect the archive for a manifest that was truncated or mis-authored.

Example fix

// before: empty manifest with metadata hash set
components: [], wasm_hash: Some(hash)
// after: either ship the component
components: vec![Component { path: "component.wasm".into(), .. }], wasm_hash: Some(hash)
// or drop the hash
components: vec![], wasm_hash: None
Defensive patterns

Strategy: validation

Validate before calling

if manifest.components.is_empty() && meta.wasm_hash.is_some() {
    return Err("wasm_hash set but manifest has no components");
}

Type guard

fn has_component_for_hash(manifest: &CapsuleManifest, meta: &CapsuleMeta) -> bool {
    !manifest.components.is_empty() || meta.wasm_hash.is_none()
}

Try / catch

match read_verified_durable_package_for_owner(&store, owner, id).await {
    Ok(pkg) => pkg,
    Err(e) if e.to_string().contains("names a component absent from its archive") => {
        // restore components or clear wasm_hash, then republish
    },
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: read_verified_durable_package_for_owner on a capsule whose manifest.components is empty but whose CapsuleMeta carries a wasm_hash value.

Common situations: A capsule stripped of its components during re-export; metadata copied from another package; manifest generation that dropped the components section while metadata survived.

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/95effa0426195675. Report an issue: GitHub.