{"record":{"id":"58cdc3d485b8707e","repo":"jdx/mise","slug":"cache-agent-returned-a-non-canonical-rustc-action","errorCode":null,"errorMessage":"cache agent returned a non-canonical rustc action prediction","messagePattern":"cache agent returned a non-canonical rustc action prediction","errorType":"exception","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/cache/rustc.rs","lineNumber":149,"sourceCode":"        invocation: invocation_digest.clone(),\n    }])?;\n    let Some(response) = responses.into_iter().next() else {\n        bail!(\"cache agent did not return an action prediction response\");\n    };\n    let prediction = match response {\n        AgentResponse::ActionPrediction {\n            prediction: Some(prediction),\n        } => prediction,\n        AgentResponse::ActionPrediction { prediction: None } => return Ok(None),\n        AgentResponse::Error { message } => bail!(message),\n        _ => bail!(\"cache agent returned an unexpected action prediction response\"),\n    };\n    if prediction.adapter != \"rustc\" || prediction.invocation != invocation_digest {\n        bail!(\"cache agent returned an incompatible rustc action prediction\");\n    }\n    let input_prediction: RustcInputPrediction = serde_json::from_str(&prediction.payload)?;\n    if String::from_utf8(canonical_json(&input_prediction)?)? != prediction.payload {\n        bail!(\"cache agent returned a non-canonical rustc action prediction\");\n    }\n    let discovered = input_prediction.discover(working_dir, &context.path_mappings)?;\n    discovered.clone().apply_to(&mut context)?;\n    let action = invocation.action(context)?;\n    let restored = restore_result(&action, outputs, &discovered, restore_outputs)?;\n    if restored.is_some() {\n        record_prediction_value(invocation_digest, action.digest.clone(), prediction.payload);\n    }\n    Ok(restored)\n}\n\nfn action_from_dep_info(\n    rustc: &OsStr,\n    invocation: &RustcInvocation,\n    dep_info: &Path,\n    working_dir: &Path,\n) -> Result<(RustcAction, DiscoveredInputs)> {\n    let dep_info = RustcDepInfo::read(dep_info)?;","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/cache/rustc.rs#L131-L167","documentation":"A prediction payload is JSON that must be in canonical form: the wrapper re-serializes the parsed RustcInputPrediction with canonical_json and requires byte-identical output to the payload received. Any difference (key ordering, whitespace, number formatting) means the agent stored or returned non-canonical JSON, so downstream digests could diverge, and the wrapper bails (src/cache/rustc.rs:149).","triggerScenarios":"An agent written by (or serialized by) a different mise version whose canonicalization differs — e.g. serde struct field order changed, float formatting changed — making the round-trip comparison fail.","commonSituations":"Upgrading mise while keeping a long-lived agent/cache; mixing release and development builds against the same cache store.","solutions":["Restart the agent and rebuild with the current mise so payloads are re-recorded canonically","Delete the agent-side cache blobs so old payloads are regenerated","Keep agent and wrapper on the same mise build; disable the rustc cache if you must mix versions"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"# Canonicalization failures mean stale payloads: reset cache and retry\ngrep -q 'non-canonical rustc action prediction' build.log && {\n  rm -rf \"$MISE_CACHE_STAGING_DIR\"; cargo build;\n}","preventionTips":["Invalidate cache stores on mise version changes","Keep one mise build (no mixing dev/release) per cache store","Monitor builds for cache warnings so drift is caught early"],"tags":["mise","rustc-cache","canonical-json","cache-agent","version-mismatch"],"backgroundTag":"cache-agent-protocol-error","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}