zeroclaw-labs/zeroclaw · error · anyhow::Error
Gemini CLI model_provider received non-finite temperature va
Error message
Gemini CLI model_provider received non-finite temperature value
What it means
GeminiCliModelProvider::validate_temperature rejects NaN and +/-inf temperatures before spawning the CLI. Only finite f64 values can be compared against the supported set, so non-finite input is a caller bug - usually arithmetic or deserialized config producing NaN upstream.
Source
Thrown at crates/zeroclaw-providers/src/gemini_cli.rs:89
binary_path: None,
}
}
/// Returns true if the model argument should be forwarded to the CLI.
fn should_forward_model(model: &str) -> bool {
let trimmed = model.trim();
!trimmed.is_empty() && trimmed != DEFAULT_MODEL_MARKER
}
fn supports_temperature(temperature: f64) -> bool {
GEMINI_CLI_SUPPORTED_TEMPERATURES
.iter()
.any(|v| (temperature - v).abs() < TEMP_EPSILON)
}
fn validate_temperature(temperature: f64) -> anyhow::Result<()> {
if !temperature.is_finite() {
anyhow::bail!("Gemini CLI model_provider received non-finite temperature value");
}
if !Self::supports_temperature(temperature) {
anyhow::bail!(
"temperature unsupported by Gemini CLI: {temperature}. \
Supported values: 0.7 or 1.0"
);
}
Ok(())
}
fn redact_stderr(stderr: &[u8]) -> String {
let text = String::from_utf8_lossy(stderr);
let trimmed = text.trim();
if trimmed.is_empty() {
return String::new();
}
if trimmed.chars().count() <= MAX_GEMINI_CLI_STDERR_CHARS {
return trimmed.to_string();View on GitHub (pinned to 88bb9c8533)
Solutions
- Sanitize at the source: reject or clamp non-finite values before they reach the provider
- Fix the arithmetic producing NaN (guard divisions, validate deserialized floats)
- Pass None to use the CLI default instead of a bogus value
Example fix
// before let temperature = base * scale; // may be NaN let text = provider.chat_with_system(None, prompt, model, Some(temperature)).await?; // after let temperature = (base * scale).is_finite().then_some(base * scale); let text = provider.chat_with_system(None, prompt, model, temperature).await?;
Defensive patterns
Strategy: validation
Validate before calling
fn safe_temperature(t: Option<f64>) -> anyhow::Result<Option<f64>> {
match t {
Some(v) if v.is_finite() => Ok(Some(v)),
Some(_) => anyhow::bail!("temperature must be finite (got NaN/inf)"),
None => Ok(None),
}
} Type guard
fn temperature_is_finite(t: f64) -> bool { t.is_finite() } Try / catch
if let Err(e) = provider.chat_with_system(None, prompt, model, Some(t)).await {
if e.to_string().contains("non-finite temperature") {
// programmer error: fix the value source, do not retry
}
return Err(e);
} Prevention
- Validate deserialized floats with is_finite() at the config boundary
- Guard any division feeding temperature math
- Fail fast at startup on non-finite config instead of at first chat call
When it happens
Trigger: Passing Some(f64::NAN) or Some(f64::INFINITY) as temperature to chat_with_system/chat_with_history; computing temperature via a division that can yield 0/0; a TOML/JSON config containing nan or inf.
Common situations: temperature = nan in config files; dynamic formulas like base * factor where factor is NaN; temperatures forwarded from another provider's response without sanitization.
Related errors
- temperature unsupported by Gemini CLI: {temperature}. Suppor
- cloud_ops.iac_tools must not be empty when cloud_ops is enab
- gateway.path_prefix contains invalid character '{bad}'; only
- risk_profiles.{profile_alias}.shell_env_passthrough[{i}] is
- security.otp.cache_valid_secs must be greater than or equal
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/c16dcc243febe090.
Report an issue: GitHub.