{"record":{"id":"1c5817450a74727a","repo":"gitui-org/gitui","slug":"wait-err","errorCode":null,"errorMessage":"wait err","messagePattern":"wait err","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/notify_mutex.rs","lineNumber":30,"sourceCode":"impl<T> NotifiableMutex<T>\nwhere\n\tT: Send + Sync,\n{\n\t///\n\tpub fn new(start_value: T) -> Self {\n\t\tSelf {\n\t\t\tdata: Arc::new((Mutex::new(start_value), Condvar::new())),\n\t\t}\n\t}\n\n\t///\n\tpub fn wait(&self, condition: T)\n\twhere\n\t\tT: PartialEq + Copy,\n\t{\n\t\tlet mut data = self.data.0.lock().expect(\"lock err\");\n\t\twhile *data != condition {\n\t\t\tdata = self.data.1.wait(data).expect(\"wait err\");\n\t\t}\n\t\tdrop(data);\n\t}\n\n\t///\n\tpub fn set_and_notify(&self, value: T) {\n\t\t*self.data.0.lock().expect(\"set err\") = value;\n\t\tself.data.1.notify_one();\n\t}\n\n\t///\n\tpub fn get(&self) -> T\n\twhere\n\t\tT: Copy,\n\t{\n\t\t*self.data.0.lock().expect(\"get err\")\n\t}\n}","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/gitui-org/gitui/blob/2fa693cb6ed431b21ebc300dd02e83c2476699ce/src/notify_mutex.rs#L12-L48","documentation":"Inside Notify::wait(), the Condvar's wait() returns Err only when the re-acquired mutex is poisoned - another thread panicked while holding it. Like the sibling 'lock err', this is a downstream symptom of an earlier panic, surfaced on whichever thread happened to be waiting on the condition variable.","triggerScenarios":"A holder thread panicking while the mutex is held (any of gitui's expect()-based panics) while a second thread sits in wait(); common during event-loop shutdown races after an initial panic.","commonSituations":"Post-panic teardown; older gitui versions with panicking worker threads; local forks that added panics in locked sections.","solutions":["Find the FIRST panic in gitui.log / scrollback and address that.","Update gitui to a current release.","For your own code: keep fallible work out of critical sections, or use parking_lot::Condvar which does not poison."],"exampleFix":"// before\nwhile *data != condition {\n    data = self.data.1.wait(data).expect(\"wait err\");\n}\n// after: recover the guard from the poison error and keep going\nwhile *data != condition {\n    data = match self.data.1.wait(data) {\n        Ok(g) => g,\n        Err(poisoned) => poisoned.into_inner(),\n    };\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"loop {\n    let guard = match cv.wait(guard) {\n        Ok(g) => g,\n        Err(poisoned) => poisoned.into_inner(), // keep waiting on the recovered guard\n    };\n    if matches!(&*guard, c if *c == condition) { break; }\n}","preventionTips":["Keep condvar/mutex critical sections minimal and panic-free.","Prefer parking_lot::Condvar/Mutex pairs, which do not poison.","When a 'wait err' appears, hunt the first panic in the log, not the waiter."],"tags":["condvar","mutex","poisoning","panic","concurrency"],"backgroundTag":"mutex-poisoned","analyzedSha":"2fa693cb6ed431b21ebc300dd02e83c2476699ce","analyzedAt":"2026-08-16T23:07:36.562Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}