Hmbown/CodeWhale · error

ConfigCommandInvalidValue

ConfigCommandInvalidValue

Error message

notifications.{key}: {value} (choices: {choices})

What it means

apply_notification_update applies a NotificationConfigUpdate to the live notifications config. When notifications.apply_update rejects the value (invalid setting or out-of-choice value), the error message is localized (MessageId::ConfigCommandInvalidValue) and interpolated with the setting key, the unusable value, and the accepted choices list. It carries code ConfigCommandInvalidValue so the config-command layer can classify it.

Solutions

  1. Use one of the listed choices shown in the error message when setting notifications.<key>.
  2. Validate the value against setting.choices() before constructing NotificationConfigUpdate.
  3. If a live delta came from an edited config file, fix the offending value there and reload.
  4. Check for typos/case differences between the provided value and the enumerated choices.

Example fix

// before
let update = NotificationConfigUpdate::new("sound", user_value);
apply_notification_update(app, config, update)?;
// after — validate first
let update = NotificationConfigUpdate::new("sound", user_value);
if !update.setting().choices().split(',').any(|c| c.trim() == user_value) {
    app.add_message(format!("notifications.sound must be one of: {}", update.setting().choices()));
    return Ok(());
}
apply_notification_update(app, config, update)?;
Defensive patterns

Strategy: validation

Validate before calling

let choices: Vec<&str> = setting.choices().split(',').map(str::trim).collect();
if !choices.contains(&provided_value.as_str()) {
    return Err(anyhow!("notifications.{} must be one of: {}", setting.key(), setting.choices()));
}

Type guard

fn is_valid_choice(value: &str, setting: &NotificationSetting) -> bool { setting.choices().split(',').any(|c| c.trim() == value) }

Try / catch

match notifications.apply_update(update) {
    Ok(()) => {},
    Err(_) => show_localized_invalid_value(setting.key(), setting.choices()),
}

Prevention

When it happens

Trigger: Calling apply_notification_update (from apply_command_result or a live notification config delta) with an update whose value is not among setting.choices() — e.g. setting notifications.<key> to a string that isn't one of the allowed enumerated choices.

Common situations: Typing an invalid value in the config command (e.g. notifications.sound=bell when choices are on/off); live config deltas from external editors using stale or wrong value names; locale-dependent message rendering showing 'unavailable' for the bad value.

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@433685b202 (2026-09-15). Data as JSON: /api/errors/5e09a46ac95ce6cd. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/tui/ui/apply.rs:1272

        // toggling the stale flag off.
        app.voice_enabled = false;
    }
    let notice = app
        .tr(MessageId::SettingLockedDuringTurn)
        .replace("{setting}", "Codewhale Runtime");
    app.push_status_toast(notice, crate::tui::app::StatusToastLevel::Info, Some(6_000));
    true
}

pub(crate) fn apply_notification_update(
    app: &mut App,
    config: &mut Config,
    update: crate::config::NotificationConfigUpdate,
) -> Result<()> {
    let mut notifications = config.notifications_config();
    let setting = update.setting();
    notifications.apply_update(update).map_err(|_| {
        anyhow::anyhow!(
            app.tr(MessageId::ConfigCommandInvalidValue)
                .replace("{key}", &format!("notifications.{}", setting.key()))
                .replace("{value}", &app.tr(MessageId::ConfigUnavailable))
                .replace("{choices}", setting.choices())
        )
    })?;
    config.notifications = Some(notifications);
    app.refresh_notification_settings(config);
    Ok(())
}

pub(crate) async fn apply_command_result(
    terminal: &mut AppTerminal,
    app: &mut App,
    engine_handle: &mut EngineHandle,
    task_manager: &SharedTaskManager,
    config: &mut Config,
    result: commands::CommandResult,

View on GitHub (pinned to 433685b202)