{"record":{"id":"7271124b179e4f48","repo":"Automattic/harper","slug":"unable-to-save-the-dictionary-to-file-err","errorCode":null,"errorMessage":"Unable to save the dictionary to file: {err}","messagePattern":"Unable to save the dictionary to file: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"harper-ls/src/backend.rs","lineNumber":162,"sourceCode":"        .await\n        .context(\"Unable to save the dictionary to path.\")\n    }\n\n    async fn load_user_dictionary(&self) -> MutableDictionary {\n        let config = self.config.read().await;\n\n        load_dict(&config.user_dict_path, self.config.read().await.dialect)\n            .await\n            .map_err(|err| info!(\"{err}\"))\n            .unwrap_or(MutableDictionary::new())\n    }\n\n    async fn save_user_dictionary(&self, dict: impl Dictionary) -> Result<()> {\n        let config = self.config.read().await;\n\n        save_dict(&config.user_dict_path, dict)\n            .await\n            .map_err(|err| anyhow!(\"Unable to save the dictionary to file: {err}\"))\n    }\n\n    async fn load_workspace_dictionary(&self) -> MutableDictionary {\n        let config = self.config.read().await;\n        load_dict(\n            &config.workspace_dict_path,\n            self.config.read().await.dialect,\n        )\n        .await\n        .map_err(|err| info!(\"{err}\"))\n        .unwrap_or(MutableDictionary::new())\n    }\n\n    async fn save_workspace_dictionary(&self, dict: impl Dictionary) -> Result<()> {\n        let config = self.config.read().await;\n        save_dict(&config.workspace_dict_path, dict)\n            .await\n            .map_err(|err| anyhow!(\"Unable to save the dictionary to file: {err}\"))","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/Automattic/harper/blob/5fe7d5ab76492d83f3ecdbc3f1da83c75dcb6f83/harper-ls/src/backend.rs#L144-L180","documentation":"`save_user_dictionary` writes the user's mutable dictionary to the configured `user_dict_path` via `save_dict`. When the underlying file write fails (I/O error, missing directory, permissions), the error is wrapped with \"Unable to save the dictionary to file\" and propagated from the `execute_command` handler (e.g. add-word-to-dictionary).","triggerScenarios":"Calling the add-to-dictionary LSP command (or execute_command path) when `user_dict_path` points to a nonexistent directory, a read-only location, or a path the process cannot create/write.","commonSituations":"user_dict_path configured relative to a workspace root that doesn't exist; read-only home or container filesystem; parent directory deleted while the server runs; path points to a directory rather than a file.","solutions":["Create the parent directory of the configured user dict path and ensure it is writable.","Check `user_dict_path` in your config points to a valid, writable file location.","Fix filesystem permissions (or run outside a read-only mount/container).","Verify disk space and that the path is not itself a directory."],"exampleFix":"// before (config)\n{ \"userDictPath\": \"./missing-dir/user-dict.txt\" }\n// after\n// mkdir missing-dir first, or point at an existing writable dir:\n{ \"userDictPath\": \"./user-dict.txt\" }","handlingStrategy":"try-catch","validationCode":"import fs from 'node:fs';\nconst dir = path.dirname(userDictPath);\nfs.mkdirSync(dir, { recursive: true });\nfs.accessSync(dir, fs.constants.W_OK);","typeGuard":null,"tryCatchPattern":"try {\n  await client.sendRequest('workspace/executeCommand', { command: 'harperLs.addUserWord', arguments: [word] });\n} catch (err) {\n  if (String(err.message).includes('Unable to save the dictionary to file')) {\n    // fix user_dict_path permissions/existence, then retry\n  }\n}","preventionTips":["Pre-create the directory containing user_dict_path","Point user_dict_path at a writable location (avoid read-only mounts/containers)","Confirm the path is a file, not a directory","Check disk space in CI/devcontainers"],"tags":["filesystem","io","dictionary","lsp"],"backgroundTag":"file-write-failed","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"}