jdx/mise · error · eyre::Report
local action keys must use blake3
Error message
local action keys must use blake3
What it means
LocalActionCache::path_for — and therefore find/store — requires action digests to use blake3, mirroring the remote client's rule for action keys. Blob digests in the CAS may use sha256, but the local action-result index (action-results/v1/blake3/<hash[0..2]>/<hash>-<size>.json) only accepts blake3 keys.
Source
Thrown at crates/mise-cache-core/src/local.rs:177
fs::set_permissions(path, permissions)?;
Ok(())
}
impl LocalActionCache {
/// Create an action-result index beneath `root`.
pub fn new(root: impl Into<PathBuf>) -> Self {
let root = root.into();
Self {
cas: LocalCas::new(root.clone()),
root,
}
}
/// Resolve the storage path for an action digest.
pub fn path_for(&self, action: &CacheDigest) -> Result<PathBuf> {
action.validate()?;
if action.algorithm != "blake3" {
bail!("local action keys must use blake3");
}
Ok(self
.root
.join("action-results/v1")
.join(&action.algorithm)
.join(&action.hash[..2])
.join(format!("{}-{}.json", action.hash, action.size)))
}
/// Find and strictly validate a canonical action result.
pub fn find(&self, action: &CacheDigest) -> Result<Option<RemoteActionResult>> {
let path = self.path_for(action)?;
if !path.exists() {
return Ok(None);
}
let bytes = fs::read(&path)?;
let result: RemoteActionResult = serde_json::from_slice(&bytes)?;
if result.version != 1 || result.action != *action || canonical_json(&result)? != bytes {View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Build action keys with CacheDigest::blake3(&canonical_json(&result)?)
- Keep one dedicated code path for action keys (blake3) even when blob digests use sha256
- Assert action.algorithm == "blake3" before calling find/store so misuse fails at the call site
Example fix
// before
let action = CacheDigest { algorithm: "sha256".into(), .. };
actions.find(&action)?;
// after
let action = CacheDigest::blake3(&canonical_json(&result)?);
actions.find(&action)?; Defensive patterns
Strategy: validation
Validate before calling
fn local_action_key(result: &RemoteActionResult) -> eyre::Result<CacheDigest> {
let bytes = mise_cache_core::canonical_json(result)?;
Ok(CacheDigest::blake3(&bytes)) // local action keys are always blake3
} Type guard
fn is_blake3_key(digest: &CacheDigest) -> bool {
digest.algorithm == "blake3" && digest.validate().is_ok()
} Prevention
- Use one blake3-only helper for action keys, separate from blob digest code
- Assert the algorithm before LocalActionCache::find/store calls
- Keep test fixtures for keys and blobs distinct so they cannot be swapped
When it happens
Trigger: Passing a sha256 CacheDigest to LocalActionCache::find or store; reusing a blob digest as an action key; porting an integration that indexed action results by sha256 before this crate pinned blake3.
Common situations: Digest plumbing where blob digests (any supported algorithm) and action keys (blake3 only) flow through the same helper; upgrades from earlier prototypes; tests sharing fixture digests between blobs and actions.
Related errors
- remote cache action keys must use blake3
- remote action manifest keys must use blake3
- local action result is invalid: {}
- unsupported remote cache digest algorithm
- invalid remote cache digest
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/79a4b0b3186b3728.
Report an issue: GitHub.