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

  1. Replace release.metadata_blake3 with the lowercase 64-hex BLAKE3 digest of the release manifest bytes (blake3::hash(bytes).to_hex()).
  2. Recompute the digest from the exact manifest file being published and regenerate the pointer.
  3. 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

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


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