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
- Set [github_relay].request_timeout to a positive duration, e.g. "30s" or "1m".
- If you meant no timeout cap, look for the max_duration setting instead — request_timeout must still be > 0.
- 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
- Never set request_timeout to 0; it must be a positive duration like "30s".
- Add config validation (or schema lint) for [github_relay] durations.
- Remember zero is invalid here even if you expect it to mean 'unlimited'; use defaults instead.
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.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- relay log format must be text or jsonl
- Invalid checksum format: {}
- {option}: '{name}' must be a plain file name (no path separa
- {option}: '{path}' must be a safe relative path (no absolute
- duration must not be negative: {}
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/1e0c3f0799c25518.
Report an issue: GitHub.