Automattic/harper · warning

ForceStable must be a boolean value.

Error message

ForceStable must be a boolean value.

What it means

Type-validation failure raised in CodeActionConfig::from_lsp_config when the "ForceStable" key in the submitted LSP configuration JSON exists but is not a JSON boolean (e.g. the string "true" or the number 1). from_lsp_config only reads ForceStable when the key is present, so this fires solely because of a malformed value type, not a missing key. The field controls whether harper-ls sorts unstable code actions (like dictionary additions) last. Fix: set "ForceStable" to true or false in the client's harper-ls settings, or remove the key to use the default.

Source

Thrown at harper-ls/src/config.rs:56

    /// Instructs `harper-ls` to place unstable code actions last.
    /// In this case, "unstable" refers to their existence and action.
    ///
    /// For example, we always want to allow users to add "misspelled" elements
    /// to dictionary, regardless of the spelling suggestions.
    pub force_stable: bool,
}

impl CodeActionConfig {
    pub fn from_lsp_config(value: Value) -> Result<Self> {
        let mut base = CodeActionConfig::default();

        let Value::Object(value) = value else {
            bail!("The code action configuration must be an object.");
        };

        if let Some(force_stable_val) = value.get("ForceStable") {
            let Value::Bool(force_stable) = force_stable_val else {
                bail!("ForceStable must be a boolean value.");
            };
            base.force_stable = *force_stable;
        };

        Ok(base)
    }
}

#[derive(Debug, Clone)]
pub struct Config {
    pub user_dict_path: PathBuf,
    pub file_dict_path: PathBuf,
    pub workspace_dict_path: PathBuf,
    pub ignored_lints_path: PathBuf,
    pub stats_path: PathBuf,
    pub lint_config: FlatConfig,
    pub diagnostic_severity: DiagnosticSeverity,
    pub code_action_config: CodeActionConfig,

View on GitHub (pinned to 5fe7d5ab76)

Solutions

  1. Change the value to a real JSON boolean: "ForceStable": true.
  2. Remove the ForceStable key entirely to accept the default.
  3. Check your editor's settings file for accidental string quoting around true/false.

Example fix

// before
"codeAction": { "ForceStable": "true" }
// after
"codeAction": { "ForceStable": true }
Defensive patterns

Strategy: validation

Validate before calling

const forceStable = settings?.harperLs?.codeAction?.forceStable;
if (forceStable !== undefined && typeof forceStable !== 'boolean') {
  throw new TypeError('ForceStable must be a boolean');
}

Type guard

fn is_bool(v: &serde_json::Value) -> bool { v.is_boolean() }

Try / catch

match CodeActionConfig::from_lsp_config(value) {
    Ok(cfg) => cfg,
    Err(e) => { log::warn!("bad codeAction config: {e}"); CodeActionConfig::default() }
}

Prevention

When it happens

Trigger: Sending codeAction settings containing `"ForceStable": "true"` (string), 1, or null to harper-ls via didChangeConfiguration/initialize options.

Common situations: Typing the setting without quotes-as-boolean in JSON (JSON has no bare true fallback when quoted), YAML/JSON5 configs where unquoted true got serialized as a string, editor plugins that pass settings through unvalidated.

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 Automattic/harper@5fe7d5ab76 (2026-09-06). Data as JSON: /api/errors/3f391f881e047bcc. Report an issue: GitHub.