Hmbown/CodeWhale · error

custom theme requires custom_theme_name

Error message

custom theme requires custom_theme_name

What it means

theme_setting_for_document (crates/tui/src/config_ui.rs:868) builds the theme setting string when /config saves. UiThemeValue::Custom is only a marker: it needs custom_theme_name to compose <USER_THEME_PREFIX><name> and resolve it through palette::resolve_theme_setting. A missing, None, or whitespace-only name fails the save with this message.

Solutions

  1. Enter a non-empty custom theme name in the adjacent field before saving
  2. Switch the theme selector to a built-in theme instead of Custom
  3. Make the UI clear the Custom selection automatically when the name field is emptied

Example fix

# before
theme = "custom"
custom_theme_name = ""

# after
theme = "custom"
custom_theme_name = "nord-dark"
Defensive patterns

Strategy: validation

Validate before calling

fn custom_theme_is_complete(doc: &ConfigUiDocument) -> bool {
    doc.settings.theme != UiThemeValue::Custom
        || doc.settings
            .custom_theme_name
            .as_deref()
            .is_some_and(|name| !name.trim().is_empty())
}

Prevention

When it happens

Trigger: Saving /config with doc.settings.theme == UiThemeValue::Custom while custom_theme_name is None or trims to empty.

Common situations: Selecting "custom" in the theme picker without typing a name; a document default that pre-selects Custom; clearing the name field but leaving the selector on Custom.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at crates/tui/src/config_ui.rs:868

        validate_and_normalize_model(config, identity.provider, model)
            .map_err(|err| anyhow::anyhow!("invalid provider_models.{provider_id} value: {err}"))?;
    }
    if doc.config.mcp_config_path.trim().is_empty() {
        bail!("mcp_config_path cannot be empty");
    }
    let _ = theme_setting_for_document(doc)?;
    Ok(())
}

fn theme_setting_for_document(doc: &ConfigUiDocument) -> Result<String> {
    let setting = if doc.settings.theme == UiThemeValue::Custom {
        let name = doc
            .settings
            .custom_theme_name
            .as_deref()
            .map(str::trim)
            .filter(|name| !name.is_empty())
            .ok_or_else(|| anyhow::anyhow!("custom theme requires custom_theme_name"))?;
        format!("{}{}", crate::palette::USER_THEME_PREFIX, name)
    } else {
        doc.settings.theme.as_setting().to_string()
    };
    crate::palette::resolve_theme_setting(&setting, None)
        .map(|(normalized, _, _)| normalized)
        .map_err(anyhow::Error::msg)
}

/// Validate and normalize a model against the provider's *effective* route.
///
/// A custom DeepSeek base URL owns its own model namespace, so non-DeepSeek ids
/// must be accepted here the same way request-time
/// `wire_model_for_provider_route` preserves them. The previous provider-only
/// gate rejected those saves even though the live session could use them.
fn validate_and_normalize_model(
    config: &Config,
    provider: crate::config::ApiProvider,

View on GitHub (pinned to 0c42157ee5)