Hmbown/CodeWhale · error
Burn rate is optional. When set, it must be a positive $/hr.
Error message
Burn rate is optional. When set, it must be a positive $/hr.
What it means
`parse_burn_rate` accepts an optional burn rate from a JSON patch (checked under several key aliases). If none of the keys yields a numeric value even though a burn-rate key was present with a non-numeric value, it bails with this message clarifying the field is optional but must be positive when supplied. The actual positivity check happens downstream in `parse_burn_amount`.
Solutions
- Send the burn rate as a JSON number, not a string: `"burnRate": 12.5`
- Omit the burn-rate key entirely if you don't want to set it (it is optional)
- Fix the key typo so the intended value is picked up
- Use `normalize_burn_rate` on raw user input before applying the patch
Example fix
// before
{"burnRate": "12.5"}
// after
{"burnRate": 12.5} Defensive patterns
Strategy: validation
Validate before calling
fn valid_burn_rate(v: &serde_json::Value) -> bool {
v.is_number() && v.as_f64().map(|n| n.is_finite() && n > 0.0).unwrap_or(false)
} Type guard
fn as_burn_amount(v: &serde_json::Value) -> Option<f64> {
v.as_f64().filter(|n| n.is_finite() && *n > 0.0)
} Try / catch
match parse_burn_rate(&patch) {
Err(e) if e.to_string().contains("must be a positive") => {
eprintln!("burnRate must be a JSON number > 0, or omit it.");
Err(e)
}
other => other,
} Prevention
- Always send burnRate as a JSON number, never a string or null
- Omit the key entirely for 'no burn rate'
- Validate patch JSON types in the client before apply
When it happens
Trigger: `apply_operate_patch` passes an operate patch whose `burnRate`/`usdPerHour`/`amount` value is present but `json_number` cannot extract a number (string, null, object, etc.), leaving `amount.is_none()` true while a key existed.
Common situations: Hand-editing a patch and writing the burn rate as a string (`"12.5"` instead of `12.5`); setting the field to `null` expecting 'unset'; UI sending wrong JSON type; key typo producing Null via `.get`.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- bundle at has kind ; expected
- Burn rate must be 10000 $/hr or less.
- Cargo metadata dependencies for
- Cargo metadata must contain workspace_members and packages…
- Cargo metadata root must be an object
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/06e9ee437365003a.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/operate.rs:255
{
return Ok(None);
}
if let Some("unbounded") = value.get("kind").and_then(|kind| kind.as_str()) {
return Ok(None);
}
let amount = if value.is_number() || value.is_string() {
json_number(value)
} else {
json_number(
value
.get("amountUsdPerHour")
.or_else(|| value.get("usdPerHour"))
.or_else(|| value.get("amount"))
.unwrap_or(&serde_json::Value::Null),
)
};
if amount.is_none() {
anyhow::bail!("Burn rate is optional. When set, it must be a positive $/hr.");
}
parse_burn_amount(amount)
}
fn json_number(value: &serde_json::Value) -> Option<f64> {
value
.as_f64()
.or_else(|| value.as_i64().map(|n| n as f64))
.or_else(|| value.as_str().and_then(|s| s.parse().ok()))
}
fn parse_burn_amount(amount: Option<f64>) -> Result<Option<OperateBurnRate>> {
let Some(amount) = amount else {
return Ok(None);
};
if !amount.is_finite() || amount <= 0.0 {
anyhow::bail!("Burn rate is optional. When set, it must be a positive $/hr.");
}View on GitHub (pinned to 433685b202)