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

  1. Derive manifest keys with blake3 over the manifest's canonical bytes and label them "blake3"
  2. Keep the digest roles distinct in your types or naming so a blob digest is never passed where a manifest key is expected
  3. 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

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


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)