Hmbown/CodeWhale · error

Failed to update setting: invalid mode

Error message

Failed to update setting: invalid mode '{value}'. Expected: act (agent), plan, or operate.

What it means

Settings::set's `default_mode`/`mode` arm maps the trimmed, lowercased value through a fixed match: agent/normal/act/work/edit -> "agent", plan -> "plan", operate/operation/ops -> "operate". Any other string hits the catch-all bail. Note `yolo` is intentionally rejected as a mode write — it survives only as a permission-migration alias.

Solutions

  1. Use act (or its aliases agent, normal, work, edit), plan, or operate (or operation, ops).
  2. If you meant the old yolo behavior, configure permission posture / sandbox_mode instead — the comment states yolo is a migration alias, not a mode.
  3. Trim whitespace and mind casing; the match lowercases for you but typos still fail.

Example fix

// before
settings.set("mode", "yolo")?;
// after
settings.set("mode", "act")?;
settings.set("permission_posture", "full-access")?;
Defensive patterns

Strategy: validation

Validate before calling

fn valid_mode(v: &str) -> bool {
    matches!(v.trim().to_ascii_lowercase().as_str(),
        "agent" | "normal" | "act" | "work" | "edit" | "plan" | "operate" | "operation" | "ops")
}

Try / catch

match settings.set("mode", value) {
    Err(e) if e.to_string().contains("invalid mode") => eprintln!("expected act, plan, or operate"),
    r => r?,
}

Prevention

When it happens

Trigger: Settings::set("mode", v) with a string outside the alias table, e.g. `mode yolo` (deliberately rejected), `mode planing`, or `mode ACT` only if a future change removes the to_ascii_lowercase normalization.

Common situations: Users upgrading from versions where `yolo` was a writable startup mode, or mistyping plan/operate (e.g. `planning`, `operation` is accepted but `operations` is not).

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/c09d9a554f71397f. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/settings.rs:1703

                let normalized = normalize_synchronized_output(value);
                if !["auto", "on", "off"].contains(&normalized) {
                    anyhow::bail!(
                        "Failed to update setting: invalid synchronized_output '{value}'. Expected: auto, on, off."
                    );
                }
                self.synchronized_output = normalized.to_string();
            }
            "workspace_follow_symlinks" | "follow_symlinks" => {
                self.workspace_follow_symlinks = parse_bool(value)?;
            }
            "default_mode" | "mode" => {
                // Act (wire: agent), Plan, and Operate are valid startup modes.
                // yolo remains a permission-migration alias, not a mode write.
                self.default_mode = match value.trim().to_ascii_lowercase().as_str() {
                    "agent" | "normal" | "act" | "work" | "edit" => "agent".to_string(),
                    "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."
                    );

View on GitHub (pinned to 73e0f67d83)