{"record":{"id":"40b0b86607a769b0","repo":"Automattic/harper","slug":"settings-must-contain-a-harper-ls-key","errorCode":null,"errorMessage":"Settings must contain a \"harper-ls\" key.","messagePattern":"Settings must contain a \"harper-ls\" key\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"harper-ls/src/config.rs","lineNumber":96,"sourceCode":"    /// Maximum length (in bytes) a file can have before it's skipped.\n    /// Above this limit, the file will not be linted.\n    pub max_file_length: usize,\n    pub exclude_patterns: GlobSet,\n}\n\nimpl Config {\n    pub fn from_lsp_config(workspace_root: &Path, value: Value) -> Result<Self> {\n        let mut base = Config::default();\n\n        let workspace_root = workspace_root.canonicalize()?;\n        let workspace_root = workspace_root.as_path();\n\n        let Value::Object(value) = value else {\n            bail!(\"Settings must be an object.\");\n        };\n\n        let Some(Value::Object(value)) = value.get(\"harper-ls\") else {\n            bail!(\"Settings must contain a \\\"harper-ls\\\" key.\");\n        };\n\n        if let Some(v) = value.get(\"userDictPath\") {\n            if !v.is_string() {\n                bail!(\"userDict path must be a string.\");\n            }\n\n            let path = v.as_str().unwrap();\n            if !path.is_empty() {\n                base.user_dict_path = path.try_resolve_in(workspace_root)?.to_path_buf();\n            }\n        }\n\n        if let Some(v) = value.get(\"fileDictPath\") {\n            if !v.is_string() {\n                bail!(\"fileDict path must be a string.\");\n            }\n","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/Automattic/harper/blob/5fe7d5ab76492d83f3ecdbc3f1da83c75dcb6f83/harper-ls/src/config.rs#L78-L114","documentation":"Config::from_lsp_config found the top-level settings object but it lacks an object-valued \"harper-ls\" key. All Harper language-server options live under that namespace, so it is mandatory in the settings payload.","triggerScenarios":"Sending settings like {\"otherServer\": {...}} or {\"harper-ls\": \"enabled\"} (non-object) to harper-ls via initialize options or didChangeConfiguration.","commonSituations":"Configuring harper-ls under the wrong server name in the editor's LSP settings; nesting harper-ls options at the top level instead of under \"harper-ls\"; sending harper-ls settings as a string or list.","solutions":["Nest all options under the \"harper-ls\" key: settings = { \"harper-ls\": { ... } }.","Verify your editor config uses the exact server name \"harper-ls\" (case-sensitive).","Send an empty object ({\"harper-ls\": {}}) if you only want defaults."],"exampleFix":"// before\n{ \"userDictPath\": \"./dict.txt\" }\n// after\n{ \"harper-ls\": { \"userDictPath\": \"./dict.txt\" } }","handlingStrategy":"validation","validationCode":"if (!settings || typeof settings['harper-ls'] !== 'object' || settings['harper-ls'] === null) {\n  throw new Error('settings must contain a \"harper-ls\" object');\n}","typeGuard":"fn has_harper_ls_section(v: &serde_json::Value) -> bool {\n    v.get(\"harper-ls\").map_or(false, |s| s.is_object())\n}","tryCatchPattern":"match Config::from_lsp_config(value, workspace_root) {\n    Ok(cfg) => cfg,\n    Err(e) => { log::warn!(\"invalid settings: {e}\"); Config::default() }\n}","preventionTips":["Nest all harper-ls options under the exact key \"harper-ls\".","Check your editor's LSP server name matches \"harper-ls\" exactly.","Start from documented example settings blocks instead of writing them from scratch."],"tags":["rust","lsp","configuration"],"backgroundTag":"missing-config-key","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"}