Hmbown/CodeWhale · error · anyhow::Error

Failed to update setting: invalid focus texture '{value}'. E

Error message

Failed to update setting: invalid focus texture '{value}'. Expected: off, scrim, or grain.

What it means

SettingsStore.update validates focus_texture and only accepts off, scrim, or grain (after trim + lowercase) (crates/tui/src/settings.rs:1254). Any other value is rejected before mutation, so the previous setting survives intact.

Source

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

            "low_motion" | "motion" => {
                self.low_motion = parse_bool(value)?;
            }
            "fancy_animations" | "fancy" | "animations" => {
                self.fancy_animations = parse_bool(value)?;
            }
            "ocean_treatment" | "treatment" | "background_treatment" => {
                let normalized = value.trim().to_ascii_lowercase();
                if !matches!(normalized.as_str(), "ombre" | "flat") {
                    anyhow::bail!(
                        "Failed to update setting: invalid ocean treatment '{value}'. Expected: ombre or flat."
                    );
                }
                self.ocean_treatment = normalized;
            }
            "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" | "left" | "right" | "off") {
                    anyhow::bail!(
                        "Failed to update setting: invalid work surface placement '{value}'. Expected: top, left, right, or off."
                    );
                }
                self.work_surface_placement = normalized;
            }
            "rail_panel" | "rail" => {
                let normalized = value.trim().to_ascii_lowercase();
                if !matches!(
                    normalized.as_str(),

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Use one of off, scrim, or grain (casing is normalized)
  2. Restrict UI inputs to a dropdown of allowed values
  3. Validate persisted settings on load and reset invalid entries to the default
  4. Re-check allowed values after upgrading the TUI

Example fix

// before
settings.update("texture", "blur")?; // invalid

// after
settings.update("texture", "scrim")?; // or "off" / "grain"
Defensive patterns

Strategy: type-guard

Validate before calling

let v = value.trim().to_ascii_lowercase();
if !matches!(v.as_str(), "off" | "scrim" | "grain") {
    return Err(anyhow::anyhow!("unsupported focus texture"));
}
settings.update("focus_texture", &v)?;

Type guard

fn is_valid_focus_texture(value: &str) -> bool {
    matches!(value.trim().to_ascii_lowercase().as_str(), "off" | "scrim" | "grain")
}

Try / catch

match settings.update("focus_texture", value) {
    Ok(()) => {}
    Err(err) if err.to_string().contains("invalid focus texture") => {
        settings.update("focus_texture", "off")?; // safe default
    }
    Err(err) => return Err(err),
}

Prevention

When it happens

Trigger: /set texture blur or settings.update("focus_texture", "none") with an unsupported value; settings files written for an older build whose texture names changed; scripts feeding free-text input straight into update

Common situations: Users typing intuitive-but-wrong names (blur, noise, none); config portability across versions; frontends not restricting the input vocabulary.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/0edd29f7b9680e80. Report an issue: GitHub.