Automattic/harper · warning

The code action configuration must be an object.

Error message

The code action configuration must be an object.

What it means

CodeActionConfig::from_lsp_config expects the incoming LSP `codeAction` settings value to be a JSON object. Anything else (null, array, string, number) is rejected with this bail, because per-key config extraction only works on a map.

Source

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

/// Configuration for how code actions are displayed.
/// Originally motivated by [#89](https://github.com/automattic/harper/issues/89).
#[derive(Debug, Clone, Default)]
pub struct CodeActionConfig {
    /// 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,

View on GitHub (pinned to 5fe7d5ab76)

Solutions

  1. Set codeAction to a proper object in your editor settings, e.g. "codeAction": { "forceStable": true } (client-side casing may differ).
  2. If you don't need code-action options, remove the codeAction key or send an empty object {}.
  3. On the server side, default to CodeActionConfig::default() when the value is null before calling from_lsp_config.

Example fix

// before (settings.json)
"harper-ls": { "codeAction": true }
// after
"harper-ls": { "codeAction": { "forceStable": false } }
Defensive patterns

Strategy: validation

Validate before calling

if (value !== null && (typeof value !== 'object' || Array.isArray(value))) {
  value = {}; // or skip the call
}
CodeActionConfig::from_lsp_config(value);

Type guard

fn is_json_object(v: &serde_json::Value) -> bool {
    matches!(v, serde_json::Value::Object(_))
}

Try / catch

match CodeActionConfig::from_lsp_config(value) {
    Ok(cfg) => cfg,
    Err(_) => CodeActionConfig::default(),
}

Prevention

When it happens

Trigger: Client sends workspace/didChangeConfiguration or initialize with codeActionLinter settings where `codeAction` is not an object — e.g. null because the client sends no codeAction section, or a wrongly-typed value in the editor's settings file.

Common situations: Editors that send `harper-ls: { codeAction: null }` when the option is unset; users writing the setting as a string/boolean instead of an object in settings.json; clients that omit codeAction entirely and the server passes the missing value straight through.

Related errors


AI-assisted analysis of Automattic/harper@5fe7d5ab76 (2026-09-06). Data as JSON: /api/errors/6f9e18b455903fe6. Report an issue: GitHub.