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
- Set codeAction to a proper object in your editor settings, e.g. "codeAction": { "forceStable": true } (client-side casing may differ).
- If you don't need code-action options, remove the codeAction key or send an empty object {}.
- 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
- Treat null settings sections as 'use defaults' before parsing.
- Keep codeAction settings as an object in editor config files.
- Validate client-side settings with a schema before sending didChangeConfiguration.
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
- ForceStable must be a boolean value.
- Settings must be an object.
- userDict path must be a string.
- Settings must contain a "harper-ls" key.
- fileDict path must be a string.
AI-assisted analysis of Automattic/harper@5fe7d5ab76 (2026-09-06).
Data as JSON: /api/errors/6f9e18b455903fe6.
Report an issue: GitHub.