jdx/mise · error
remote action manifest keys must use blake3
Error message
remote action manifest keys must use blake3
What it means
Thrown by action_manifest_endpoint (crates/mise-cache-core/src/lib.rs:474) when the key for a task action-manifest request validates but is not blake3. Manifest keys, like action keys, must be blake3 digests; the endpoint path v{PROTOCOL_VERSION}/action-manifests/{algorithm}/{hash}/{size} only accepts algorithm == "blake3".
Solutions
- Derive manifest keys with blake3 over the manifest's canonical bytes and label them "blake3"
- Keep the digest roles distinct in your types or naming so a blob digest is never passed where a manifest key is expected
- Align with the protocol: both action results and action manifests are blake3-keyed; only blob payloads may additionally be sha256
Example fix
// before
let key = CacheDigest { algorithm: "sha256".into(), hash: sha256_hex(&manifest_bytes), size };
// after
let key = CacheDigest { algorithm: "blake3".into(), hash: blake3::hash(&manifest_bytes).to_hex().to_string(), size }; Defensive patterns
Strategy: type-guard
Validate before calling
fn is_blake3_key(key: &CacheDigest) -> bool { key.algorithm == "blake3" }
if !is_blake3_key(&manifest_key) { return Err("manifest keys must be blake3"); } Type guard
fn is_valid_manifest_key(k: &CacheDigest) -> bool {
k.algorithm == "blake3" && k.hash.len() == 64
&& k.hash.bytes().all(|b| b.is_ascii_digit() || (b'a'..=b'f').contains(&b))
} Try / catch
if !is_valid_manifest_key(&key) { rebuild_key_with_blake3(&manifest_bytes)?; }
client.put_action_manifest(&key, &bytes, expected_etag).await?; Prevention
- Derive manifest keys with blake3 over the exact serialized manifest bytes
- Name variables manifest_key/blob_digest/action_key to keep the three roles from being swapped
- Unit-test that every key you send passes key.validate() plus the blake3 check
When it happens
Trigger: Calling get_action_manifest/put_action_manifest (and the ETag-verified GET path around lib.rs:710-726) with a key built from sha256 or another algorithm — e.g. deriving the manifest key by sha256 of the task name, or accidentally passing a blob digest as the manifest key.
Common situations: Code that hashes manifest keys with whatever hasher was in scope; version skew with a producer using a different key algorithm; confusion between the three digest roles (action key, manifest key, blob digest).
Related errors
- action prediction payload is too large
- remote action manifest ETag does not match its body
- task action manifest contains duplicate predictions
- task action manifest has an invalid identity
- brew-cask: invalid command_wrapper environment name
AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22).
Data as JSON: /api/errors/a85c0fd79bff84ca.
Report an issue: GitHub.
Appendix: source
Thrown at crates/mise-cache-core/src/lib.rs:474
}
Ok(self.base_url.join(&format!(
"v{PROTOCOL_VERSION}/action-results/{}/{}/{}",
action.algorithm, action.hash, action.size
))?)
}
fn blob_endpoint(&self, digest: &CacheDigest) -> Result<Url> {
digest.validate()?;
Ok(self.base_url.join(&format!(
"v{PROTOCOL_VERSION}/blobs/{}/{}/{}",
digest.algorithm, digest.hash, digest.size
))?)
}
fn action_manifest_endpoint(&self, key: &CacheDigest) -> Result<Url> {
key.validate()?;
if key.algorithm != "blake3" {
bail!("remote action manifest keys must use blake3");
}
Ok(self.base_url.join(&format!(
"v{PROTOCOL_VERSION}/action-manifests/{}/{}/{}",
key.algorithm, key.hash, key.size
))?)
}
fn capabilities_endpoint(&self) -> Result<Url> {
Ok(self
.base_url
.join(&format!("v{PROTOCOL_VERSION}/capabilities"))?)
}
fn blob_pack_endpoint(&self) -> Result<Url> {
Ok(self
.base_url
.join(&format!("v{PROTOCOL_VERSION}/blobs:pack"))?)
}View on GitHub (pinned to 6f52dcdf99)