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` parses a burn-rate value out of an operate patch JSON. Burn rate itself is optional, but if the incoming JSON provides none of the recognized keys (`usdPerHour`, `amount`, or the primary key), the value is treated as `None` and rejected: providing the field in a way that resolves to nothing is invalid. The message states the contract — optional, but positive $/hr when present.

Solutions

  1. Either omit the burn-rate field entirely (it is optional) or supply a positive numeric value under a recognized key (`usdPerHour` / `amount`).
  2. Fix the payload key name so the number lands under `usdPerHour` or `amount`.
  3. If you intended zero, remove the field — zero is not accepted either.

Example fix

// before
{"burnRate": {}}
// after
{"burnRate": {"usdPerHour": 5.0}}
// or remove the field entirely
Defensive patterns

Strategy: validation

Validate before calling

fn burn_rate_payload_ok(v: &serde_json::Value) -> bool {
    let obj = match v.get("burnRate") { Some(o) => o, None => return true }; // optional
    obj.get("usdPerHour").or_else(|| obj.get("amount"))
      .map(|n| n.as_f64().map_or(false, |x| x.is_finite() && x > 0.0))
      .unwrap_or(false)
}

Try / catch

match parse_burn_rate(&patch) {
    Err(e) if e.to_string().contains("Burn rate is optional") => {
        // drop or correct the burnRate field and resubmit
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling `parse_burn_rate` (via `apply_operate_patch` or tests) with a JSON object that has a burn-rate field present but with no recognizable amount key, so `amount` is `None` — e.g. `"burnRate": {}` or `"burnRate": null` explicitly supplied.

Common situations: Hand-writing an operate patch with an empty or null burn-rate object; a UI sending `usdPerHour` under a wrong key name the parser doesn't know; API version drift where the payload key changed.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). 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 73e0f67d83)