{"record":{"id":"16438cbe2546dc5a","repo":"gitbutlerapp/gitbutler","slug":"could-not-read-settings-e","errorCode":null,"errorMessage":"Could not read settings: {e:?}","messagePattern":"Could not read settings: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-settings/src/watch.rs","lineNumber":96,"sourceCode":"        config_dir: impl AsRef<Path>,\n        customization: Option<serde_json::Value>,\n    ) -> Result<Self> {\n        let config_path = config_dir.as_ref().join(SETTINGS_FILE);\n        let app_settings = AppSettings::load(&config_path, customization.clone())?;\n        let app_settings = Arc::new(RwLock::new(app_settings));\n\n        Ok(Self {\n            config_path,\n            snapshot: app_settings,\n            customization,\n        })\n    }\n\n    /// Return a reference to the most recently loaded [`AppSettings`].\n    pub fn get(&self) -> Result<RwLockReadGuard<'_, AppSettings>> {\n        self.snapshot\n            .read()\n            .map_err(|e| anyhow::anyhow!(\"Could not read settings: {e:?}\"))\n    }\n\n    /// Allow changes only from within this crate to implement all possible settings updates [here](crate::api).\n    pub(crate) fn get_mut_enforce_save(&self) -> Result<AppSettingsEnforceSaveToDisk<'_>> {\n        self.snapshot\n            .write()\n            .map(|snapshot| AppSettingsEnforceSaveToDisk {\n                snapshot,\n                config_path: &self.config_path,\n                saved: false,\n                customization: self.customization.clone(),\n            })\n            .map_err(|e| anyhow::anyhow!(\"Could not write settings: {e:?}\"))\n    }\n\n    /// The path from which application settings will be read from disk.\n    pub fn config_path(&self) -> &Path {\n        &self.config_path","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-settings/src/watch.rs#L78-L114","documentation":"The settings watcher's RwLock read failed, which in Rust means the lock is poisoned: some thread panicked while holding the write lock on the AppSettings snapshot. Every later get() then reports this wrapper error instead of settings.","triggerScenarios":"Calling AppSettingsWatcher::get() (or any read of the settings snapshot) after a panic occurred inside get_mut_enforce_save or a settings-mutation code path that held the write lock across the panic.","commonSituations":"A bug in a settings-save routine panics once; from then on every settings read in the process fails with this error until restart. Typically seen in logs as a cascade right after an unrelated panic message.","solutions":["Search the log for the FIRST panic before this error — the panic is the root cause, this error is fallout","Fix or handle the panic in the settings-mutation path (often a disk I/O unwrap or serialization panic)","Restart the application to clear the poisoned lock after fixing or working around the root panic","If writing new settings code, never unwrap inside get_mut_enforce_save's guard scope"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match watcher.get() {\n    Ok(settings) => { /* use settings */ }\n    Err(e) if e.to_string().contains(\"Could not read settings\") => {\n        // lock poisoned — restart-worthy state; fall back to defaults if acceptable\n        AppSettings::default()\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Never unwrap/panic while holding the settings write lock — propagate Results instead","Log the first panic in the process; poisoned locks are always secondary damage","Expose a health check that reports lock poisoning so the app can restart cleanly"],"tags":["rust","rwlock","poisoned-lock","panic-recovery","but-settings"],"backgroundTag":"mutex-poisoned","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}