Hmbown/CodeWhale · error

Failed to update setting: invalid work surface placement

Error message

Failed to update setting: invalid work surface placement '{value}'. Expected: top, bottom, left, right, or off.

What it means

The settings setter rejected the value given for `work_surface_placement`. Accepted values are top, bottom, left, right, or off (case-insensitive, trimmed). The guard prevents an invalid rail placement from corrupting the layout config.

Solutions

  1. Use one of: top, bottom, left, right, or off.
  2. Use `off` to hide the work surface rail instead of an invented keyword.
  3. Verify the alias you used resolves to work_surface_placement in settings.rs.

Example fix

// before
settings.set("work_surface_placement", "floating")
// after
settings.set("work_surface_placement", "left")
Defensive patterns

Strategy: validation

Validate before calling

const PLACEMENTS: [&str; 5] = ["top", "bottom", "left", "right", "off"];
fn valid_work_surface_placement(v: &str) -> bool {
    PLACEMENTS.contains(&v.trim().to_ascii_lowercase().as_str())
}

Try / catch

if let Err(e) = settings.set("work_surface_placement", value) {
    eprintln!("{e}"); // message lists all accepted placements
}

Prevention

When it happens

Trigger: Settings update with key `work_surface_placement` (aliases `work_surface`, `work_rail`) and a value outside {top, bottom, left, right, off}, e.g. `set work_rail floating`.

Common situations: Typing a placement keyword from another tool; assuming diagonal or auto placements exist; typo like `bottom-right`.

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/7cef68eaa679d975. Report an issue: GitHub.

Appendix: source

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

            "fancy_animations" | "fancy" | "animations" => {
                self.fancy_animations = parse_bool(value)?;
            }
            "focus_texture" | "texture" => {
                let normalized = value.trim().to_ascii_lowercase();
                if !matches!(normalized.as_str(), "off" | "scrim" | "grain") {
                    anyhow::bail!(
                        "Failed to update setting: invalid focus texture '{value}'. Expected: off, scrim, or grain."
                    );
                }
                self.focus_texture = normalized;
            }
            "work_surface_placement" | "work_surface" | "work_rail" => {
                let normalized = value.trim().to_ascii_lowercase();
                if !matches!(
                    normalized.as_str(),
                    "top" | "bottom" | "left" | "right" | "off"
                ) {
                    anyhow::bail!(
                        "Failed to update setting: invalid work surface placement '{value}'. Expected: top, bottom, left, right, or off."
                    );
                }
                self.work_surface_placement = normalized;
            }
            "rail_panel" | "rail" => {
                let normalized = value.trim().to_ascii_lowercase();
                // `pinned` stays accepted as a setting word; it folds into
                // the tasks view exactly like the load-time migration.
                if !matches!(
                    normalized.as_str(),
                    "tasks"
                        | "agents"
                        | "background"
                        | "files"
                        | "notepad"
                        | "context"
                        | "git"

View on GitHub (pinned to 73e0f67d83)