{"record":{"id":"2693cfe655b4ceb5","repo":"nikivdev/code","slug":"timeout-must-be-a-positive-finite-number","errorCode":null,"errorMessage":"timeout must be a positive finite number","messagePattern":"timeout must be a positive finite number","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/url_inspect.rs","lineNumber":894,"sourceCode":"    };\n\n    Ok(UrlInspectResult {\n        reference: url.to_string(),\n        provider: \"direct\".to_string(),\n        final_url: Some(final_url),\n        status_code: Some(status.as_u16()),\n        content_type,\n        title,\n        description,\n        excerpt,\n        markdown,\n        cache_hit: None,\n    })\n}\n\nfn timeout_from_secs(seconds: f64) -> Result<Duration> {\n    if !seconds.is_finite() || seconds <= 0.0 {\n        bail!(\"timeout must be a positive finite number\");\n    }\n    Ok(Duration::from_secs_f64(seconds))\n}\n\nfn cloudflare_credentials() -> Result<Option<(String, String)>> {\n    let account_id = load_secret_env_var(\"CLOUDFLARE_ACCOUNT_ID\")?;\n    let api_token = load_secret_env_var(\"CLOUDFLARE_API_TOKEN\")?;\n    match (account_id, api_token) {\n        (Some(account_id), Some(api_token)) => Ok(Some((account_id, api_token))),\n        (None, None) => Ok(None),\n        (Some(_), None) => {\n            bail!(\"missing CLOUDFLARE_API_TOKEN; set it in shell env or Flow personal env store\")\n        }\n        (None, Some(_)) => {\n            bail!(\"missing CLOUDFLARE_ACCOUNT_ID; set it in shell env or Flow personal env store\")\n        }\n    }\n}","sourceCodeStart":876,"sourceCodeEnd":912,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/url_inspect.rs#L876-L912","documentation":"timeout_from_secs validates a caller-supplied f64 timeout in seconds before converting it to a Duration. It rejects NaN, infinities, zero, and negative values because Duration::from_secs_f64 would panic on them. This is pure input validation guarding against a downstream panic.","triggerScenarios":"Calling inspect_compact, inspect, or crawl with a timeout_seconds value that is 0.0, negative, NaN, or infinite — typically parsed from CLI flags or JSON config.","commonSituations":"Config file containing timeout: 0, a misparsed or missing numeric field defaulting to 0.0, NaN produced by a failed float parse, or a negative value meant to mean 'no timeout'.","solutions":["Pass a positive finite value, e.g. timeout_seconds: 30.0.","Validate/clamp user input before calling: ensure the value parses as a finite positive f64.","If 'unlimited' was intended, use a large finite sentinel (e.g. 3600.0) since 0/negative is rejected.","Fix the config source (env var, JSON) so it supplies a real number instead of 0 or null-coerced 0.0."],"exampleFix":"// before\nlet timeout = config.timeout_seconds; // 0.0 from default\n// after\nlet timeout = if config.timeout_seconds.is_finite() && config.timeout_seconds > 0.0 {\n    config.timeout_seconds\n} else {\n    30.0 // sane default\n};","handlingStrategy":"validation","validationCode":"fn valid_timeout(seconds: f64) -> bool {\n    seconds.is_finite() && seconds > 0.0\n}\n\nassert!(valid_timeout(config.timeout_seconds), \"timeout must be a positive finite number\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Clamp/validate timeout inputs at the config-parsing boundary.","Use a default (e.g. 30s) when the value is missing or zero.","Avoid sentinel 0/negative for 'no timeout'; use a large finite value.","Parse timeouts as f64 explicitly and reject NaN early."],"tags":["rust","validation","configuration","arguments"],"backgroundTag":"invalid-argument-value","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}