{"record":{"id":"2d3764d970af5c4b","repo":"jdx/mise","slug":"remote-action-result-does-not-match-requested-acti","errorCode":null,"errorMessage":"remote action result does not match requested action","messagePattern":"remote action result does not match requested action","errorType":"exception","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"crates/mise-cache-core/src/lib.rs","lineNumber":378,"sourceCode":"                .request(reqwest::Method::GET, url.clone(), ACTION_RESULT_MEDIA_TYPE)\n                .await?\n                .send()\n                .await?;\n            if response.status() == StatusCode::NOT_FOUND {\n                return Ok(None);\n            }\n            Ok(Some(\n                response\n                    .error_for_status()?\n                    .json::<RemoteActionResult>()\n                    .await?,\n            ))\n        })\n        .await?;\n        if let Some(result) = &result\n            && (result.version != 1 || result.action != *action)\n        {\n            bail!(\"remote action result does not match requested action\");\n        }\n        Ok(result)\n    }\n\n    pub async fn put_action_result(&self, result: &RemoteActionResult) -> Result<()> {\n        let url = self.action_result_endpoint(&result.action)?;\n        let body = serde_json::to_vec(result)?;\n        retry_async(\"PUT\", &url, self.retries, || async {\n            let response = self\n                .request(reqwest::Method::PUT, url.clone(), ACTION_RESULT_MEDIA_TYPE)\n                .await?\n                .header(CONTENT_TYPE, ACTION_RESULT_MEDIA_TYPE)\n                .header(IF_NONE_MATCH, \"*\")\n                .body(body.clone())\n                .send()\n                .await?;\n            if response.status() != StatusCode::PRECONDITION_FAILED {\n                response.error_for_status()?;","sourceCodeStart":360,"sourceCodeEnd":396,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/crates/mise-cache-core/src/lib.rs#L360-L396","documentation":"After a successful GET, the client verifies the returned RemoteActionResult has version == 1 and an action field equal to the requested digest. A mismatch means the server answered with a record belonging to a different action or protocol generation — treated as corruption or cache poisoning rather than a hit. The error is deterministic, so neither the built-in retry loop nor a manual retry of the same request will help.","triggerScenarios":"A cache server that ignores the mise-cache-namespace header or the algorithm/hash/size path and returns the wrong record; a reverse proxy serving a response cached under a different key; a server implementing a different protocol version (version != 1); a corrupted record stored under the right key.","commonSituations":"A shared reverse proxy in front of the cache that does not vary on the namespace or protocol headers; version skew after upgrading the cache server; multiple projects reusing one namespace on a server that keys only by hash.","solutions":["Treat the error as a cache miss: rebuild locally and optionally overwrite with put_action_result","Verify the server keys action-results by the full algorithm/hash/size URL path and honors the namespace header","Configure any proxy/CDN in front of the cache to vary on mise-cache-namespace and mise-cache-protocol","Confirm client and server agree on PROTOCOL_VERSION (currently 1)"],"exampleFix":"// before\nlet result = client.get_action_result(&action).await?; // propagates mismatch error\n\n// after: degrade to a miss on integrity failures\nlet result = match client.get_action_result(&action).await {\n    Ok(result) => result,\n    Err(report) if report.to_string().contains(\"does not match requested action\") => None,\n    Err(report) => return Err(report),\n};","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"let result = match client.get_action_result(&action).await {\n    Ok(result) => result,\n    Err(report) if report.to_string().contains(\"does not match requested action\") => {\n        // poisoned/corrupt entry: treat as a miss and rebuild\n        None\n    }\n    Err(report) => return Err(report),\n};","preventionTips":["Verify proxies vary on mise-cache-namespace and mise-cache-protocol headers","Pin client and server to the same protocol version in CI","Always structure cache reads so an integrity failure can degrade to a local rebuild"],"tags":["remote-cache","integrity","action-result","protocol","cache-poisoning"],"backgroundTag":"cache-corruption","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}