{"record":{"id":"6f9e18b455903fe6","repo":"Automattic/harper","slug":"the-code-action-configuration-must-be-an-object","errorCode":null,"errorMessage":"The code action configuration must be an object.","messagePattern":"The code action configuration must be an object\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"harper-ls/src/config.rs","lineNumber":51,"sourceCode":"\n/// Configuration for how code actions are displayed.\n/// Originally motivated by [#89](https://github.com/automattic/harper/issues/89).\n#[derive(Debug, Clone, Default)]\npub struct CodeActionConfig {\n    /// Instructs `harper-ls` to place unstable code actions last.\n    /// In this case, \"unstable\" refers to their existence and action.\n    ///\n    /// For example, we always want to allow users to add \"misspelled\" elements\n    /// to dictionary, regardless of the spelling suggestions.\n    pub force_stable: bool,\n}\n\nimpl CodeActionConfig {\n    pub fn from_lsp_config(value: Value) -> Result<Self> {\n        let mut base = CodeActionConfig::default();\n\n        let Value::Object(value) = value else {\n            bail!(\"The code action configuration must be an object.\");\n        };\n\n        if let Some(force_stable_val) = value.get(\"ForceStable\") {\n            let Value::Bool(force_stable) = force_stable_val else {\n                bail!(\"ForceStable must be a boolean value.\");\n            };\n            base.force_stable = *force_stable;\n        };\n\n        Ok(base)\n    }\n}\n\n#[derive(Debug, Clone)]\npub struct Config {\n    pub user_dict_path: PathBuf,\n    pub file_dict_path: PathBuf,\n    pub workspace_dict_path: PathBuf,","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/Automattic/harper/blob/5fe7d5ab76492d83f3ecdbc3f1da83c75dcb6f83/harper-ls/src/config.rs#L33-L69","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (settings.json)\n\"harper-ls\": { \"codeAction\": true }\n// after\n\"harper-ls\": { \"codeAction\": { \"forceStable\": false } }","handlingStrategy":"validation","validationCode":"if (value !== null && (typeof value !== 'object' || Array.isArray(value))) {\n  value = {}; // or skip the call\n}\nCodeActionConfig::from_lsp_config(value);","typeGuard":"fn is_json_object(v: &serde_json::Value) -> bool {\n    matches!(v, serde_json::Value::Object(_))\n}","tryCatchPattern":"match CodeActionConfig::from_lsp_config(value) {\n    Ok(cfg) => cfg,\n    Err(_) => CodeActionConfig::default(),\n}","preventionTips":["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."],"tags":["rust","lsp","configuration","json"],"backgroundTag":"config-type-mismatch","analyzedSha":"5fe7d5ab76492d83f3ecdbc3f1da83c75dcb6f83","analyzedAt":"2026-09-06T11:34:38.610Z","contentChangedAt":"2026-09-06T11:34:38.610Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}