jdx/mise · error

invalid GitHub relay timeout policy

Error message

invalid GitHub relay timeout policy

What it means

The connected relay advertises its timeout policy in the x-mise-relay-timeout header, parsed as a Duration. adapter_client validates that the duration is non-zero and that it can be added to the current instant without overflow; a zero duration or an unparseable/overflowing value is rejected with "invalid GitHub relay timeout policy" so the client never builds a client with a useless or overflowing read timeout.

Source

Thrown at src/github_relay.rs:1026

        let response = builder()
            .build()?
            .get("http://localhost/_session")
            .timeout(Duration::from_secs(3))
            .send()
            .await
            .map_err(|error| {
                eyre::Report::new(error.without_url()).wrap_err("GitHub relay policy unavailable")
            })?;
        if response.status() != 204 {
            bail!("GitHub relay is not connected");
        }
        let value = response
            .headers()
            .get("x-mise-relay-timeout")
            .ok_or_else(|| eyre::eyre!("GitHub relay timeout policy missing"))?;
        let timeout: Duration = serde_json::from_slice(value.as_bytes())?;
        if timeout.is_zero() || std::time::Instant::now().checked_add(timeout).is_none() {
            bail!("invalid GitHub relay timeout policy");
        }
        Ok((builder().read_timeout(timeout).build()?, timeout))
    }

    // Bound connecting and writing as well as waiting for response headers.
    // The client's read timeout separately protects the streamed response.
    async fn send_adapter_request(
        req: reqwest::RequestBuilder,
        timeout: Duration,
    ) -> Result<reqwest::Response> {
        tokio::time::timeout(timeout, req.send())
            .await
            .map_err(|_| eyre::eyre!("GitHub relay request setup timed out"))?
            .map_err(|error| {
                eyre::Report::new(error.without_url())
                    .wrap_err("GitHub relay disconnected or unavailable")
            })
    }

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Update the relay and client to matching versions so the x-mise-relay-timeout header is serialized consistently.
  2. Restart the session to get a fresh relay process emitting a valid timeout policy.
  3. Remove any intermediary proxy on the relay's loopback path that could strip or rewrite the custom header.
Defensive patterns

Strategy: try-catch

Try / catch

match result {
    Err(e) if e.to_string().contains("invalid GitHub relay timeout policy") => {
        // restart the relay/session to get a fresh, valid header
    }
    other => other?,
}

Prevention

When it happens

Trigger: The relay responds 204 but its x-mise-relay-timeout header is missing-valid: it's "0", absent of proper Duration serialization, corrupted, or absurdly large enough to overflow Instant::checked_add.

Common situations: Version mismatch between client and relay where the header format changed; a broken/patched relay build emitting a zero timeout; proxy middleware stripping or mangling the custom header.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/8d6939ea4ff507ad. Report an issue: GitHub.