astrid-runtime/astrid · error
capsule provenance envelope exceeds 64 KiB
Error message
capsule provenance envelope exceeds 64 KiB
What it means
Finally, verify_release_manifest requires the manifest's targets table to be byte-for-byte equal to the targets embedded in the signed channel pointer (after validate_targets passed on the manifest itself). This error means the set of platform targets — their asset URLs/digests — differs between the manifest and the signed pointer, so the client cannot trust which artifacts belong to this release.
Source
Thrown at crates/astrid-build/src/artifact.rs:271
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> {
let path = entry.path().context("invalid capsule archive path")?;
let mut parts = Vec::new();
for component in path.components() {
match component {View on GitHub (pinned to affd8760f4)
Solutions
- Re-sign the channel pointer with the exact same targets table as the current manifest (or vice versa: publish the manifest matching the pointer's targets).
- Regenerate both artifacts together in the release pipeline so targets are captured once and reused.
- If a target was legitimately added post-release, cut a new generation of the pointer including it.
Example fix
# before: pointer targets [[targets]] triple = "x86_64-unknown-linux-gnu" # manifest also has aarch64-apple-darwin -> mismatch # after: regenerate pointer including all manifest targets pointer.targets = manifest.targets.clone();
Defensive patterns
Strategy: validation
Validate before calling
fn targets_match(m: &ReleaseManifest, p: &ChannelPointer) -> bool {
m.targets == p.targets
} Try / catch
match verify_release_manifest(&bytes, &pointer) {
Err(e) if e.to_string().contains("targets do not match") => eprintln!("re-fetch both artifacts or re-sign pointer with current targets"),
other => other,
} Prevention
- Generate pointer and manifest from one shared release descriptor
- Treat targets as immutable post-signing
- Diff targets in CI before publishing
When it happens
Trigger: verify_release_manifest (via resolve_signed_channel or workflow_identity_and_metadata_digest_are_exact) finds manifest.targets != pointer.targets after validate_targets(&manifest.targets, &manifest.version) succeeded.
Common situations: A new platform target added to the manifest but the pointer was signed earlier without it; a target's asset hash or URL changed on a re-upload; pointer generated from a template with a default target list; partial rollback of one target.
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
- capsule archive entry '{requested}' is not a regular file
- capsule archive contains duplicate entry '{path}'
- capsule archive contains unsupported entry '{path}'
- unsupported schema-version {} (expected {SCHEMA_VERSION})
- distro.id '{}' is invalid (must match ^[a-z][a-z0-9-]*$)
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/20af03e95b92ecee.
Report an issue: GitHub.