jdx/mise · error · eyre::Report

remote action result does not match requested action

Error message

remote action result does not match requested action

What it means

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.

Source

Thrown at crates/mise-cache-core/src/lib.rs:378

                .request(reqwest::Method::GET, url.clone(), ACTION_RESULT_MEDIA_TYPE)
                .await?
                .send()
                .await?;
            if response.status() == StatusCode::NOT_FOUND {
                return Ok(None);
            }
            Ok(Some(
                response
                    .error_for_status()?
                    .json::<RemoteActionResult>()
                    .await?,
            ))
        })
        .await?;
        if let Some(result) = &result
            && (result.version != 1 || result.action != *action)
        {
            bail!("remote action result does not match requested action");
        }
        Ok(result)
    }

    pub async fn put_action_result(&self, result: &RemoteActionResult) -> Result<()> {
        let url = self.action_result_endpoint(&result.action)?;
        let body = serde_json::to_vec(result)?;
        retry_async("PUT", &url, self.retries, || async {
            let response = self
                .request(reqwest::Method::PUT, url.clone(), ACTION_RESULT_MEDIA_TYPE)
                .await?
                .header(CONTENT_TYPE, ACTION_RESULT_MEDIA_TYPE)
                .header(IF_NONE_MATCH, "*")
                .body(body.clone())
                .send()
                .await?;
            if response.status() != StatusCode::PRECONDITION_FAILED {
                response.error_for_status()?;

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Treat the error as a cache miss: rebuild locally and optionally overwrite with put_action_result
  2. Verify the server keys action-results by the full algorithm/hash/size URL path and honors the namespace header
  3. Configure any proxy/CDN in front of the cache to vary on mise-cache-namespace and mise-cache-protocol
  4. Confirm client and server agree on PROTOCOL_VERSION (currently 1)

Example fix

// before
let result = client.get_action_result(&action).await?; // propagates mismatch error

// after: degrade to a miss on integrity failures
let result = match client.get_action_result(&action).await {
    Ok(result) => result,
    Err(report) if report.to_string().contains("does not match requested action") => None,
    Err(report) => return Err(report),
};
Defensive patterns

Strategy: fallback

Try / catch

let result = match client.get_action_result(&action).await {
    Ok(result) => result,
    Err(report) if report.to_string().contains("does not match requested action") => {
        // poisoned/corrupt entry: treat as a miss and rebuild
        None
    }
    Err(report) => return Err(report),
};

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/2d3764d970af5c4b. Report an issue: GitHub.