jdx/mise · error

relay request timeout must be greater than zero

Error message

relay request timeout must be greater than zero

What it means

configure parses the relay request timeout from settings.github_relay.request_timeout (or explicit overrides) and requires it to be strictly greater than zero. A zero timeout would disable request timing entirely, so mise rejects it as invalid configuration. A companion check also bounds relay concurrency to 1..=32.

Source

Thrown at src/github_relay.rs:98

    no_log_requests: bool,
    format: Option<&str>,
    max_duration: Option<&str>,
) -> Result<Option<Scope>> {
    let Some(scope) = scope else {
        if log_requests || no_log_requests || format.is_some() || max_duration.is_some() {
            bail!("relay options require --github-relay-read-only");
        }
        return Ok(None);
    };
    let settings = crate::config::Settings::get();
    let settings = &settings.github_relay;
    let format = format.unwrap_or(&settings.log_format);
    if !matches!(format, "text" | "jsonl") {
        bail!("relay log format must be text or jsonl");
    }
    let timeout = duration::parse_duration(&settings.request_timeout)?;
    if timeout.is_zero() {
        bail!("relay request timeout must be greater than zero");
    }
    if !(1..=32).contains(&settings.concurrency) {
        bail!("relay concurrency must be between 1 and 32");
    }
    let max_duration = duration::parse_duration(max_duration.unwrap_or(&settings.max_duration))?;
    if std::time::Instant::now().checked_add(timeout).is_none()
        || std::time::Instant::now()
            .checked_add(max_duration)
            .is_none()
    {
        bail!("relay duration is too large");
    }
    #[cfg(not(unix))]
    let _ = max_duration;
    #[cfg(unix)]
    let scope = {
        let mut scope = scope;
        scope.options = Options {

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Set [github_relay].request_timeout to a positive duration, e.g. "30s" or "1m".
  2. If you meant no timeout cap, look for the max_duration setting instead — request_timeout must still be > 0.
  3. Omit the setting to use mise's built-in default request timeout.

Example fix

// before (mise.toml)
[github_relay]
request_timeout = "0"
// after
[github_relay]
request_timeout = "30s"
Defensive patterns

Strategy: validation

Validate before calling

let t = duration::parse_duration(&settings.github_relay.request_timeout)?;
assert!(!t.is_zero(), "request_timeout must be > 0");

Type guard

fn has_positive_timeout(s: &GithubRelaySettings) -> bool {
    duration::parse_duration(&s.request_timeout).map_or(false, |d| !d.is_zero())
}

Try / catch

match configure(scope, lr, nlr, format, max_duration) {
    Err(e) if e.to_string().contains("timeout must be greater than zero") => {
        // reset request_timeout to a sane default and retry
    }
    r => r,
}

Prevention

When it happens

Trigger: duration::parse_duration succeeds but the resulting Duration is zero — i.e. [github_relay].request_timeout = "0" / "0s" / "0ms" in mise.toml or settings, then npm_command or cli_observability_overrides calls configure.

Common situations: Someone setting request_timeout = "0" believing it means 'unlimited'; copy-pasting template configs with placeholder zero values; unit mistakes like "0s" when intending seconds-long defaults.

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/1e0c3f0799c25518. Report an issue: GitHub.