astrid-runtime/astrid · error

capsule archive contains unsupported entry '{path}'

Error message

capsule archive contains unsupported entry '{path}'

What it means

The manifest's contracts section must reference the official contracts repository (CONTRACTS_REPOSITORY) and a syntactically valid 40-hex source commit (is_commit). This binds the release to a specific, valid revision of the contracts package. The error means the manifest names the wrong contracts repo or carries a malformed commit hash.

Source

Thrown at crates/astrid-build/src/artifact.rs:267

    let mut records = Vec::new();
    let mut envelope = None;
    let mut seen = HashSet::new();

    for entry in archive
        .entries()
        .context("failed to read capsule archive")?
    {
        let mut entry = entry.context("failed to read capsule archive entry")?;
        let path = normalized_entry_path(&entry)?;
        if !seen.insert(path.clone()) {
            bail!("capsule archive contains duplicate entry '{path}'");
        }
        let kind = entry.header().entry_type();
        if kind.is_dir() {
            continue;
        }
        if !kind.is_file() {
            bail!("capsule archive contains unsupported entry '{path}'");
        }
        if path == PROVENANCE_FILE {
            if entry.size() > 64 * 1024 {
                bail!("capsule provenance envelope exceeds 64 KiB");
            }
            let mut bytes = Vec::new();
            entry
                .read_to_end(&mut bytes)
                .context("failed to read capsule provenance")?;
            envelope = Some(bytes);
            continue;
        }
        records.push(hash_reader(path, entry.size(), &mut entry)?);
    }
    Ok((records, envelope))
}

fn normalized_entry_path<R: Read>(entry: &tar::Entry<'_, R>) -> anyhow::Result<String> {

View on GitHub (pinned to affd8760f4)

Solutions

  1. Set manifest.contracts.repository to the official CONTRACTS_REPOSITORY value and contracts.commit to the full 40-char lowercase hex commit.
  2. Regenerate the manifest with the release tooling so the contracts revision is stamped from the actual build.
  3. If contracts moved repos, update CONTRACTS_REPOSITORY/tooling and reissue both manifest and pointer.

Example fix

# before
[contracts]
repository = "github.com/acme/contracts-old"
commit = "abc123"
# after
[contracts]
repository = "acme/contracts"
commit = "0123456789abcdef0123456789abcdef01234567"
Defensive patterns

Strategy: validation

Validate before calling

fn contracts_ok(repo: &str, commit: &str, expected_repo: &str) -> bool {
    repo == expected_repo && commit.len() == 40
        && commit.bytes().all(|b| matches!(b, b'0'..=b'9' | b'a'..=b'f'))
}

Type guard

fn is_commit(s: &str) -> bool {
    s.len() == 40 && s.bytes().all(|b| matches!(b, b'0'..=b'9' | b'a'..=b'f'))
}

Try / catch

match verify_release_manifest(&bytes, &pointer) {
    Err(e) if e.to_string().contains("contracts identity is invalid") => eprintln!("regenerate manifest with valid contracts repo/commit"),
    other => other,
}

Prevention

When it happens

Trigger: verify_release_manifest parses a manifest whose contracts.repository != CONTRACTS_REPOSITORY, or whose contracts.commit fails is_commit (not 40 lowercase hex chars).

Common situations: Manifest generated against a forked contracts repo; placeholder commit ('HEAD', short SHA, or 'TBD') left in the manifest; upstream contracts repository migrated and manifest generated with the old org/name; manual manifest authoring.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


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