astrid-runtime/astrid · error
Distro.lock capsule '{capsule}' requires a canonical blake3:
Error message
Distro.lock capsule '{capsule}' requires a canonical blake3:<hex> WASM hash What it means
Distro.lock WASM hashes must use the canonical 'blake3:<64 hex chars>' form. parse_locked_blake3 rejects any value without the blake3: prefix, since non-prefixed or foreign-algorithm hashes cannot be verified against the content store.
Source
Thrown at crates/astrid-cli/src/commands/init_grant.rs:426
let blob_path = home.bin_dir().join(format!("{locked_hex}.wasm"));
std::fs::read(&blob_path).with_context(|| {
format!(
"Distro.lock capsule '{}' content blob is missing or unreadable at {}",
capsule,
blob_path.display()
)
})?
};
let actual = blake3::hash(&bytes);
if actual != locked {
bail!("Distro.lock capsule '{capsule}' content blob bytes do not match hash {locked_hash}");
}
Ok(())
}
fn parse_locked_blake3(capsule: &CapsuleId, value: &str) -> anyhow::Result<blake3::Hash> {
let Some(hex) = value.strip_prefix("blake3:") else {
bail!("Distro.lock capsule '{capsule}' requires a canonical blake3:<hex> WASM hash");
};
let hash = blake3::Hash::from_hex(hex).map_err(|_| {
anyhow::anyhow!("Distro.lock capsule '{capsule}' has an invalid BLAKE3 hash")
})?;
if hex.len() != 64 || hash.to_hex().as_str() != hex {
bail!("Distro.lock capsule '{capsule}' requires a canonical lowercase BLAKE3 hash");
}
Ok(hash)
}
fn manifest_declares_wasm(manifest: &CapsuleManifest) -> bool {
manifest
.components
.iter()
.any(|component| component.path.extension().and_then(|ext| ext.to_str()) == Some("wasm"))
}
/// Apply capsule-access grants for the installed set (opt-in), or printView on GitHub (pinned to affd8760f4)
Solutions
- Rewrite the Distro.lock hash as blake3:<64-char lowercase hex>.
- Regenerate Distro.lock with the current CLI so hashes are emitted canonically.
- Recompute the artifact hash with blake3 (not sha256/xxhash) and store it with the prefix.
Example fix
// before (Distro.lock) hash = "9f86d081884c7d659a2f..." // after hash = "blake3:9f86d081884c7d659a2f..."
Defensive patterns
Strategy: validation
Validate before calling
if !locked_hash.starts_with("blake3:") {
return Err(anyhow!("hash must be blake3:<hex>"));
} Type guard
fn is_blake3_lock_hash(v: &str) -> bool {
v.strip_prefix("blake3:")
.map(|h| h.len() == 64 && h.bytes().all(|b| b.is_ascii_hexdigit()))
.unwrap_or(false)
} Try / catch
match parse_locked_blake3(capsule, value) {
Err(e) if e.to_string().contains("canonical blake3:") => fix_hash_prefix(capsule)?,
other => other?,
} Prevention
- Always emit hashes as blake3:<64 lowercase hex> in tooling.
- Lint the lockfile format in CI.
- Never copy hashes from sha256 or other digest outputs.
When it happens
Trigger: parse_locked_blake3 (called from validate_locked_wasm) receives a locked_hash where strip_prefix("blake3:") returns None — e.g. a bare hex digest, a sha256: prefix, or an empty string.
Common situations: Hand-edited lockfile dropping the prefix, lockfile written by an older tool using a different hash format, copy-pasting a digest from a non-blake3 tool.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Distro.lock capsule '{capsule}' requires a canonical lowerca
- capsule archive already contains {PROVENANCE_FILE}
- Distro.lock capsule '{}' hash disagrees with the daemon regi
- Distro.lock capsule '{capsule}' declares WASM but has no ins
- Distro.lock non-WASM capsule '{capsule}' must not carry a WA
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/62d02790ada12aff.
Report an issue: GitHub.