Hmbown/CodeWhale · error
Failed to update setting: invalid cost currency
Error message
Failed to update setting: invalid cost currency '{value}'. Expected: usd, cny, rmb, yuan. What it means
Settings::set resolves the `cost_currency`/`currency` value through crate::pricing::CostCurrency::from_setting. When that returns None the setter bails. The canonical storage values are "usd" and "cny"; the error additionally advertises rmb and yuan as accepted spellings of CNY.
Solutions
- Use usd, cny, rmb, or yuan.
- If you need another currency, it is not implemented — file/inspect a feature request in the pricing module.
- Verify the exact string in CostCurrency::from_setting in crates/tui/src/pricing.rs.
Example fix
// before
settings.set("cost_currency", "eur")?;
// after
settings.set("cost_currency", "usd")?; Defensive patterns
Strategy: validation
Validate before calling
fn valid_currency(v: &str) -> bool {
matches!(v.trim().to_ascii_lowercase().as_str(), "usd" | "cny" | "rmb" | "yuan")
} Try / catch
match settings.set("cost_currency", value) {
Err(e) if e.to_string().contains("invalid cost currency") => eprintln!("only USD and CNY are supported"),
r => r?,
} Prevention
- Check the supported currency list before exposing a currency picker in wrappers.
- Do not invent currency codes; only USD/CNY exist.
- Normalize CNY aliases (rmb, yuan) to cny in your own input handling.
When it happens
Trigger: Settings::set("cost_currency", v) where from_setting(v) returns None — e.g. `currency EUR`, `currency dollars`, or a trailing-space/emoji variant the parser does not strip.
Common situations: Users wanting costs displayed in a currency that is not supported (only USD and CNY exist), or typing informal currency names (bucks, ¥).
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
- A pinned task provider requires an explicit model
- Failed to update setting: invalid mode
- Failed to update setting: invalid ocean treatment
- Failed to update setting: invalid permission posture
- Failed to update setting: invalid status indicator
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/cc1bc93b03ebb3ed.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/settings.rs:1719
"plan" => "plan".to_string(),
"operate" | "operation" | "ops" => "operate".to_string(),
_ => anyhow::bail!(
"Failed to update setting: invalid mode '{value}'. Expected: act (agent), plan, or operate."
),
};
}
"context_panel" | "context" | "session_panel" => {
self.context_panel = parse_bool(value)?;
}
"sessions_rail" | "sessions_panel" | "session_rail" => {
self.sessions_rail = parse_bool(value)?;
}
"session_auto_resume" | "auto_resume" => {
self.session_auto_resume = parse_bool(value)?;
}
"cost_currency" | "currency" => {
let Some(currency) = crate::pricing::CostCurrency::from_setting(value) else {
anyhow::bail!(
"Failed to update setting: invalid cost currency '{value}'. Expected: usd, cny, rmb, yuan."
);
};
self.cost_currency = match currency {
crate::pricing::CostCurrency::Usd => "usd",
crate::pricing::CostCurrency::Cny => "cny",
}
.to_string();
}
"max_history" | "history" => {
let max: usize = value.parse().map_err(|_| {
anyhow::anyhow!(
"Failed to update setting: invalid max history '{value}'. Expected a positive number."
)
})?;
self.max_input_history = max;
}
"default_model" | "model" => {View on GitHub (pinned to 73e0f67d83)