jdx/mise · error · eyre::Report
remote action manifest keys must use blake3
Error message
remote action manifest keys must use blake3
What it means
Action-manifest keys are scoped like action-result keys: blake3 only. action_manifest_endpoint() validates the digest and then rejects any algorithm other than "blake3" before constructing the URL for get_action_manifest/put_action_manifest. This keeps manifest keys consistent with the blake3 ETag contract used for manifest bodies.
Source
Thrown at crates/mise-cache-core/src/lib.rs:326
}
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
))?)
}
async fn request(
&self,
method: reqwest::Method,
url: Url,
media_type: &'static str,
) -> Result<reqwest::RequestBuilder> {
let request = self
.client
.request(method, url)
.header(PROTOCOL_HEADER, u16::from(PROTOCOL_VERSION))
.header(NAMESPACE_HEADER, &self.namespace)View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Derive manifest keys with CacheDigest::blake3 over the exact manifest bytes
- Keep one code path for key digests (blake3) and a separate one for blob digests if you need sha256 blobs
- Add a debug assert or pre-check that key.algorithm == "blake3" before calling the manifest endpoints
Example fix
// before
let key = CacheDigest { algorithm: "sha256".into(), hash, size };
client.get_action_manifest(&key).await?;
// after
let key = CacheDigest::blake3(&manifest_bytes);
client.get_action_manifest(&key).await?; Defensive patterns
Strategy: validation
Validate before calling
fn manifest_key(bytes: &[u8]) -> CacheDigest {
CacheDigest::blake3(bytes) // manifest keys are always blake3
}
fn ensure_manifest_key(key: &CacheDigest) -> eyre::Result<()> {
key.validate()?;
if key.algorithm != "blake3" {
eyre::bail!("manifest key must use blake3, got {}", key.algorithm);
}
Ok(())
} Type guard
fn is_blake3_manifest_key(key: &CacheDigest) -> bool {
key.algorithm == "blake3" && key.validate().is_ok()
} Prevention
- Derive manifest keys from the exact manifest bytes with CacheDigest::blake3
- Never route manifest keys through a configurable-algorithm hashing helper
- Type-separate key digests from blob digests in your data model so they cannot be swapped
When it happens
Trigger: Passing a sha256 CacheDigest as the key to RemoteCacheClient::get_action_manifest or put_action_manifest; deriving the manifest key from a sha256 blob digest; shared helper code that hashes keys with a configurable algorithm defaulting to sha256.
Common situations: Code paths that compute blob digests (any algorithm) and manifest keys (blake3 only) with the same function; integrations upgraded from an earlier prototype that used sha256 manifest keys.
Related errors
- remote cache action keys must use blake3
- remote action manifest ETag does not match its body
- unsupported remote cache digest algorithm
- invalid remote cache digest
- invalid remote action manifest ETag
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/a85c0fd79bff84ca.
Report an issue: GitHub.