astrid-runtime/astrid · error

durable capsule {id} is missing WIT file {relative}

Error message

durable capsule {id} is missing WIT file {relative}

What it means

verify_wit_files looks up each WIT file listed in the capsule metadata under the `wit/` key in the archive's in-memory file map. If the archive does not contain the file the metadata pins, the package is internally inconsistent — metadata and archive disagree — and reading the durable package fails rather than silently missing an interface definition.

Source

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

    let mut expected = std::collections::BTreeSet::new();
    for (relative, pin) in &metadata.wit_files {
        let relative_path = Path::new(relative);
        if relative_path.is_absolute()
            || relative_path.components().any(|component| {
                matches!(
                    component,
                    std::path::Component::ParentDir | std::path::Component::RootDir
                )
            })
            || relative_path
                .components()
                .any(|component| !matches!(component, std::path::Component::Normal(_)))
        {
            bail!("durable capsule {id} has unsafe WIT metadata path {relative}");
        }
        let key = format!("wit/{relative}");
        let Some(bytes) = files.get(&key) else {
            bail!("durable capsule {id} is missing WIT file {relative}");
        };
        if !is_hex_digest(pin) || blake3::hash(bytes).to_hex().as_str() != pin {
            bail!("durable capsule {id} WIT digest mismatch for {relative}");
        }
        expected.insert(key);
    }
    for key in files.keys().filter(|key| key.starts_with("wit/")) {
        if Path::new(key)
            .extension()
            .is_some_and(|extension| extension.eq_ignore_ascii_case("wit"))
            && !expected.contains(key)
        {
            bail!("durable capsule {id} has an unpinned WIT file {key}");
        }
    }
    Ok(())
}

View on GitHub (pinned to affd8760f4)

Solutions

  1. Re-add the missing .wit file to the capsule source and republish/reinstall the capsule.
  2. Regenerate metadata so wit_files matches the actual archive contents (rebuild the capsule package).
  3. If the archive was truncated in transit, re-download/reinstall from the registry.
  4. Verify consistency locally before publishing by digesting the built archive.

Example fix

// before: metadata pins types.wit but archive lacks it
// metadata.wit_files = {"types.wit": pin}; archive has only wit/api.wit
// after: restore or republish so both sides agree
cp types.wit wit/ && republish capsule
Defensive patterns

Strategy: validation

Validate before calling

fn all_pinned_wits_present(metadata_wit_files: &[(String, String)], archive_files: &[String]) -> bool {
    metadata_wit_files.iter().all(|(rel, _)| archive_files.iter().any(|f| f == &format!("wit/{rel}")))
}

Type guard

fn wit_file_in_archive(rel: &str, files: &std::collections::BTreeMap<String, Vec<u8>>) -> bool {
    files.contains_key(&format!("wit/{rel}"))
}

Try / catch

match read_verified_durable_package_for_owner(id) {
    Err(e) if e.to_string().contains("is missing WIT file") => {
        // metadata/archive disagreement: republish or reinstall the capsule
        reinstall_capsule(id)?;
    }
    other => other?,
}

Prevention

When it happens

Trigger: read_verified_durable_package_for_owner on a capsule where metadata.wit_files declares a relative path whose corresponding `wit/<relative>` entry is absent from the archive files — e.g. the WIT file was deleted or renamed after metadata was generated, or the archive was rebuilt without it.

Common situations: Renaming/removing a .wit file without republishing; partial archive upload/truncation dropping files; editing the durable store to update one side only; version drift between metadata and archive.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — 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/32541379233f14ba. Report an issue: GitHub.