{"record":{"id":"e792017cf42b41f8","repo":"ducaale/xh","slug":"connection-timeout-is-negative","errorCode":null,"errorMessage":"Connection timeout is negative","messagePattern":"Connection timeout is negative","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli.rs","lineNumber":1204,"sourceCode":"}\n\n#[derive(Debug, Clone)]\npub struct Timeout(Duration);\n\nimpl Timeout {\n    pub fn as_duration(&self) -> Option<Duration> {\n        Some(self.0).filter(|t| !t.is_zero())\n    }\n}\n\nimpl FromStr for Timeout {\n    type Err = anyhow::Error;\n\n    fn from_str(sec: &str) -> anyhow::Result<Timeout> {\n        match f64::from_str(sec) {\n            Ok(s) if !s.is_nan() => {\n                if s.is_sign_negative() {\n                    Err(anyhow!(\"Connection timeout is negative\"))\n                } else if s >= Duration::MAX.as_secs_f64() || s.is_infinite() {\n                    Err(anyhow!(\"Connection timeout is too big\"))\n                } else {\n                    Ok(Timeout(Duration::from_secs_f64(s)))\n                }\n            }\n            _ => Err(anyhow!(\"Connection timeout is not a valid number\")),\n        }\n    }\n}\n\n#[derive(Debug, Clone, PartialEq, Eq)]\npub enum Proxy {\n    Http(Url),\n    Https(Url),\n    All(Url),\n}\n","sourceCodeStart":1186,"sourceCodeEnd":1222,"githubUrl":"https://github.com/ducaale/xh/blob/2404aceecc08b0b2d100fedc96f57745cd5904dc/src/cli.rs#L1186-L1222","documentation":"Validation guard in Timeout's FromStr impl: the --connection-timeout value parsed as f64 has a negative sign (e.g. '-5' or '-0.0' signed zero), so it cannot represent a valid duration and parsing aborts with an anyhow error before a Timeout is constructed. Fires whenever the user supplies a negative numeric timeout on the command line.","triggerScenarios":"Passing --timeout=-5, --timeout=-0.001, or --timeout=-0 to any flag parsed into Timeout.","commonSituations":"Scripts parameterizing timeout with an unset/default negative sentinel; sign errors when computing timeout from offsets.","solutions":["Supply a non-negative timeout value (e.g. --timeout=5)","Clamp computed timeout values to >= 0 before passing them","Omit --timeout to use the default"],"exampleFix":"# before\nhttp --timeout=-5 GET example.org\n# after\nhttp --timeout=5 GET example.org","handlingStrategy":"validation","validationCode":"// validate the timeout string before invoking\nlet v: f64 = timeout_str.parse().map_err(|_| \"invalid timeout\")?;\nif v.is_sign_negative() || v.is_nan() { return Err(\"timeout must be non-negative\"); }","typeGuard":"fn is_valid_timeout(s: &str) -> bool {\n    s.parse::<f64>().map(|v| !v.is_nan() && !v.is_sign_negative() && v < 1.7976931348623157e308).unwrap_or(false)\n}","tryCatchPattern":"let out = Command::new(\"http\").args([\"--timeout\", &timeout_str, \"GET\", url]).output()?;\nif !out.status.success() && String::from_utf8_lossy(&out.stderr).contains(\"timeout is negative\") {\n    eprintln!(\"clamp timeout to >= 0 and retry\");\n}","preventionTips":["Clamp computed timeout values to a small positive minimum","Guard against unset env vars defaulting to negative sentinels","Validate numeric inputs with sign checks before passing"],"tags":["cli","timeout","validation"],"backgroundTag":"value-out-of-range","analyzedSha":"2404aceecc08b0b2d100fedc96f57745cd5904dc","analyzedAt":"2026-09-13T19:13:33.814Z","contentChangedAt":"2026-09-13T19:13:33.814Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}