ducaale/xh · error
Connection timeout is not a valid number
Error message
Connection timeout is not a valid number
What it means
Final fallthrough guard in Timeout's FromStr impl: f64::from_str failed for the --connection-timeout argument, meaning the input is not a parseable number (e.g. 'abc' or an empty string), or it was NaN. The match on the parse result falls into the error arm and parsing of the timeout value aborts. Fires on any non-numeric or NaN timeout input.
Solutions
- Pass a plain numeric value in seconds (e.g. --timeout=30)
- Strip unit suffixes and convert to seconds before passing
- Quote/escape values in scripts to avoid empty strings
- Validate the value with f64 parsing (excluding NaN) beforehand
Example fix
# before http --timeout=30s GET example.org # after http --timeout=30 GET example.org
Defensive patterns
Strategy: validation
Validate before calling
// validate the timeout is a plain number before invoking
let v: f64 = timeout_str.trim().parse().map_err(|_| "timeout must be a plain number of seconds, no unit suffix")?;
if v.is_nan() { return Err("timeout must not be NaN"); } Type guard
fn is_valid_timeout(s: &str) -> bool {
s.trim().parse::<f64>().map(|v| !v.is_nan()).unwrap_or(false)
} Try / catch
let out = Command::new("http").args(["--timeout", &timeout_str, "GET", url]).output()?;
if !out.status.success() && String::from_utf8_lossy(&out.stderr).contains("not a valid number") {
eprintln!("'{timeout_str}' is not a bare number of seconds");
} Prevention
- Pass bare numbers only; convert '30s'/'5m' to seconds yourself
- Trim whitespace and guard empty env vars before passing
- Reject NaN values in input validation
When it happens
Trigger: Passing --timeout=abc, --timeout='', --timeout=5s (suffix not allowed), or --timeout=NaN.
Common situations: Including time units like '30s' or '5m' (only bare numbers/seconds are accepted); locale-formatted decimals; empty values from unset env vars.
Understand the failure class
Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- is not a valid value
- Connection timeout is negative
- Connection timeout is too big
- message-signature: RSA private keys require an explicit…
- Unsupported option
AI-assisted analysis of ducaale/xh@2404aceecc (2026-09-13).
Data as JSON: /api/errors/c1e170224952eab1.
Report an issue: GitHub.
Appendix: source
Thrown at src/cli.rs:1211
Some(self.0).filter(|t| !t.is_zero())
}
}
impl FromStr for Timeout {
type Err = anyhow::Error;
fn from_str(sec: &str) -> anyhow::Result<Timeout> {
match f64::from_str(sec) {
Ok(s) if !s.is_nan() => {
if s.is_sign_negative() {
Err(anyhow!("Connection timeout is negative"))
} else if s >= Duration::MAX.as_secs_f64() || s.is_infinite() {
Err(anyhow!("Connection timeout is too big"))
} else {
Ok(Timeout(Duration::from_secs_f64(s)))
}
}
_ => Err(anyhow!("Connection timeout is not a valid number")),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Proxy {
Http(Url),
Https(Url),
All(Url),
}
impl FromStr for Proxy {
type Err = anyhow::Error;
fn from_str(s: &str) -> anyhow::Result<Self> {
let split_arg: Vec<&str> = s.splitn(2, ':').collect();
match split_arg[..] {
[protocol, url] => {View on GitHub (pinned to 2404aceecc)