jdx/mise · error · eyre::Report
local action result is invalid: {}
Error message
local action result is invalid: {} What it means
LocalActionCache::find strictly validates a stored action-result file: version must equal 1, the record's action field must equal the requested digest, and the file bytes must exactly equal canonical_json of the parsed record. Any deviation — truncation, pretty-printing, a stale format, or a record stored under the wrong key — is treated as corruption and the offending path is included in the message.
Source
Thrown at crates/mise-cache-core/src/local.rs:196
}
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 {
bail!("local action result is invalid: {}", path.display());
}
Ok(Some(result))
}
/// Atomically publish an action result after validating all referenced objects.
pub fn store(&self, result: &RemoteActionResult) -> Result<PathBuf> {
if result.version != 1 {
bail!("unsupported local action result version");
}
for digest in [
Some(&result.action),
result.metadata.as_ref(),
result.output_root.as_ref(),
]
.into_iter()
.flatten()
{
if self.cas.find(digest)?.is_none() {View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Delete the offending .json file named in the error — LocalActionCache::store automatically replaces invalid entries on the next publish
- If many entries fail, clear the action-results directory (or the whole cache root) and repopulate from rebuilds
- Keep editors, formatters, and sync tools away from the cache root
- After upgrades, treat the old cache as disposable instead of migrating files by hand
Example fix
# before: actions.find(&action) fails with # local action result is invalid: /home/u/.cache/mise/action-results/v1/blake3/ab/abcd1234…-57.json # after: remove the corrupt record (store() rewrites it on the next publish) rm /home/u/.cache/mise/action-results/v1/blake3/ab/abcd1234…-57.json
Defensive patterns
Strategy: fallback
Try / catch
let result = match actions.find(&action) {
Ok(result) => result,
Err(report) if report.to_string().contains("local action result is invalid") => {
// corrupt record: delete it, treat as a miss; store() rewrites it on next publish
let _ = std::fs::remove_file(actions.path_for(&action)?);
None
}
Err(report) => return Err(report),
}; Prevention
- Never edit, format, or migrate files under the cache root by hand
- Note that LocalActionCache::store transparently replaces invalid entries — prefer re-storing over manual surgery
- After format-changing upgrades, clear the action-results directory rather than converting it
When it happens
Trigger: A JSON file under action-results/v1/ that was hand-edited or reformatted (breaking canonical byte equality); truncation from a crash in an older non-atomic writer; files written by a previous version with different canonicalization or version; a result written under another action's key.
Common situations: Developers or formatters 'normalizing' JSON inside the cache directory; power loss during writes before atomic persist existed; upgrading mise/cache tooling across format versions; tools that reserialize JSON on save.
Related errors
- local CAS blob failed digest verification: {}
- local action keys must use blake3
- remote cache action keys must use blake3
- remote action result does not match requested action
- bytes do not match the declared CAS digest
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/e7a8af3cb1e7554c.
Report an issue: GitHub.