{"record":{"id":"7c915d786071dcf4","repo":"zeroclaw-labs/zeroclaw","slug":"kilocli-model-provider-received-non-finite-tempera","errorCode":null,"errorMessage":"KiloCLI model_provider received non-finite temperature value","messagePattern":"KiloCLI model_provider received non-finite temperature value","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-providers/src/kilocli.rs","lineNumber":89,"sourceCode":"            binary_path: None,\n        }\n    }\n\n    /// Returns true if the model argument should be forwarded to the CLI.\n    fn should_forward_model(model: &str) -> bool {\n        let trimmed = model.trim();\n        !trimmed.is_empty() && trimmed != DEFAULT_MODEL_MARKER\n    }\n\n    fn supports_temperature(temperature: f64) -> bool {\n        KILO_CLI_SUPPORTED_TEMPERATURES\n            .iter()\n            .any(|v| (temperature - v).abs() < TEMP_EPSILON)\n    }\n\n    fn validate_temperature(temperature: f64) -> anyhow::Result<()> {\n        if !temperature.is_finite() {\n            anyhow::bail!(\"KiloCLI model_provider received non-finite temperature value\");\n        }\n        if !Self::supports_temperature(temperature) {\n            anyhow::bail!(\n                \"temperature unsupported by KiloCLI: {temperature}. \\\n                 Supported values: 0.7 or 1.0\"\n            );\n        }\n        Ok(())\n    }\n\n    fn redact_stderr(stderr: &[u8]) -> String {\n        let text = String::from_utf8_lossy(stderr);\n        let trimmed = text.trim();\n        if trimmed.is_empty() {\n            return String::new();\n        }\n        if trimmed.chars().count() <= MAX_KILO_CLI_STDERR_CHARS {\n            return trimmed.to_string();","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-providers/src/kilocli.rs#L71-L107","documentation":"KiloCLI's validate_temperature rejects NaN and infinite temperatures before the `kilo` process is spawned. As with the other CLI wrappers, the CLI takes no sampling parameter, so the value is validated only to catch corrupt input early. Non-finite values come from config literals (`nan`/`inf`) or upstream arithmetic (0/0, overflow).","triggerScenarios":"A chat call on a KiloCliModelProvider with temperature = NaN or +/-inf: hand-edited config, computed division without a zero guard, or parsed \"NaN\"/\"Infinity\" strings from user input.","commonSituations":"Agent profiles shared across providers where one producer can emit NaN; normalization code that divides by a count that can be zero; lenient numeric parsing of external input.","solutions":["Guard the producer: verify `is_finite()` before passing temperature to chat","Fix or delete the `temperature` key in the agent/config file","Pass Some(0.7) or Some(1.0) — the only supported values for kilocli"],"exampleFix":"// before\nlet temp: f64 = input.parse().unwrap_or(f64::NAN);\nprovider.chat(req, model, Some(temp)).await?;\n\n// after\nlet temp: f64 = input.parse().ok().filter(|v| v.is_finite()).unwrap_or(0.7);\nprovider.chat(req, model, Some(temp)).await?;","handlingStrategy":"validation","validationCode":"fn temperature_safe(t: Option<f64>) -> bool {\n    t.map(f64::is_finite).unwrap_or(true)\n}","typeGuard":"fn is_finite_temperature(t: f64) -> bool { t.is_finite() }","tryCatchPattern":"if let Err(e) = kilo.chat(req, model, temp).await {\n    if e.to_string().contains(\"non-finite temperature\") {\n        // fix the value producer; retrying the same input cannot succeed\n    }\n}","preventionTips":["Validate is_finite() on computed temperatures before the call","Block `nan`/`inf` in config schema validation for kilocli agents"],"tags":["kilocli","temperature","nan","infinity","validation"],"backgroundTag":"nan-parameter-value","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}