astrid-runtime/astrid · error
capsule archive already contains {PROVENANCE_FILE}
Error message
capsule archive already contains {PROVENANCE_FILE} What it means
The pointer's release.metadata_blake3 must be exactly 64 lowercase hex characters (a BLAKE3 hex digest). This ensure! fails when the digest field is absent-of-shape: wrong length, uppercase, or non-hex characters, meaning the manifest bytes later could not be integrity-checked against it.
Source
Thrown at crates/astrid-build/src/artifact.rs:91
#[must_use]
pub fn content_digest(&self) -> &str {
match self {
Self::Unsigned { content_digest } => content_digest,
Self::Signed(provenance) => &provenance.content_digest,
}
}
}
/// Sign a freshly-created capsule archive with the selected runtime key.
///
/// # Errors
///
/// Fails when the archive is malformed, already contains a provenance entry,
/// contains unsafe or duplicate entries, or cannot be replaced atomically.
pub fn sign_archive(archive_path: &Path, keypair: &KeyPair) -> anyhow::Result<VerifiedProvenance> {
let (records, envelope) = read_archive(archive_path)?;
if envelope.is_some() {
bail!("capsule archive already contains {PROVENANCE_FILE}");
}
let content_digest = digest_records(records)?;
let signature = keypair.sign(&signature_message(&content_digest));
let provenance = VerifiedProvenance {
content_digest: content_digest.clone(),
signer: keypair.export_public_key(),
signature,
};
let envelope = ProvenanceEnvelope {
schema_version: SCHEMA_VERSION,
algorithm: ALGORITHM.to_string(),
content_digest,
signer: provenance.signer,
signature,
};
rewrite_with_provenance(archive_path, &serde_json::to_vec_pretty(&envelope)?)?;
Ok(provenance)
}View on GitHub (pinned to affd8760f4)
Solutions
- Replace release.metadata_blake3 with the lowercase 64-hex BLAKE3 digest of the release manifest bytes (blake3::hash(bytes).to_hex()).
- Recompute the digest from the exact manifest file being published and regenerate the pointer.
- Ensure your tooling emits lowercase hex (avoid to_uppercase or base64 mixups).
Example fix
// before metadata_blake3 = "ABCDEF..." // uppercase / wrong length // after let digest = blake3::hash(&manifest_bytes).to_hex(); // 64 lowercase hex metadata_blake3 = digest.to_string();
Defensive patterns
Strategy: validation
Validate before calling
fn valid_blake3_hex(s: &str) -> bool {
s.len() == 64 && s.bytes().all(|b| matches!(b, b'0'..=b'9' | b'a'..=b'f'))
} Type guard
fn is_lower_hex_64(s: &str) -> bool {
s.len() == 64 && s.bytes().all(|b| matches!(b, b'0'..=b'9' | b'a'..=b'f'))
} Try / catch
match parse_channel(&bytes, channel, now) {
Err(e) if e.to_string().contains("metadata BLAKE3 is invalid") => eprintln!("recompute lowercase blake3 hex digest"),
other => other,
} Prevention
- Compute digests with blake3::hash(...).to_hex() into the struct directly
- Pre-publish assert is_lower_hex_64 on digest fields
- Never paste digests by hand
When it happens
Trigger: validate_pointer (via parse_channel or enforce_continuity) encounters a ChannelPointer whose release.metadata_blake3 fails is_lower_hex_64 (not 64 chars of [0-9a-f]).
Common situations: Uppercase digest pasted from a tool that prints uppercase hex; truncated digest; BLAKE3 vs SHA-256 confusion (64 vs 40/64 hex); placeholder value left in a template.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- Distro.lock capsule '{capsule}' has an invalid BLAKE3 hash
- opaque capsule asset directories cannot be symlinks: {}
- opaque asset path must be a directory: {}
- WASM binary not found at {}
- capsule archive contains duplicate entry '{requested}'
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/9ab5a938e8141e9d.
Report an issue: GitHub.