{"record":{"id":"85ab67683aeabeef","repo":"affaan-m/ECC","slug":"current-dir-test-lock-poisoned","errorCode":null,"errorMessage":"current-dir test lock poisoned","messagePattern":"current-dir test lock poisoned","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"ecc2/src/main.rs","lineNumber":28,"sourceCode":"#[cfg(test)]\npub(crate) mod test_support {\n    use anyhow::{Context, Result};\n    use std::path::{Path, PathBuf};\n    use std::sync::{Mutex, MutexGuard, OnceLock};\n\n    static CURRENT_DIR_LOCK: OnceLock<Mutex<()>> = OnceLock::new();\n\n    pub(crate) struct CurrentDirGuard {\n        _lock: MutexGuard<'static, ()>,\n        original_dir: PathBuf,\n    }\n\n    impl CurrentDirGuard {\n        pub(crate) fn enter(target_dir: &Path) -> Result<Self> {\n            let lock = CURRENT_DIR_LOCK\n                .get_or_init(|| Mutex::new(()))\n                .lock()\n                .expect(\"current-dir test lock poisoned\");\n            let original_dir =\n                std::env::current_dir().context(\"Failed to capture current test directory\")?;\n            std::env::set_current_dir(target_dir).with_context(|| {\n                format!(\"Failed to enter test directory {}\", target_dir.display())\n            })?;\n\n            Ok(Self {\n                _lock: lock,\n                original_dir,\n            })\n        }\n    }\n\n    impl Drop for CurrentDirGuard {\n        fn drop(&mut self) {\n            let _ = std::env::set_current_dir(&self.original_dir);\n        }\n    }","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/ecc2/src/main.rs#L10-L46","documentation":"CurrentDirGuard::enter acquires a global process-wide mutex (CURRENT_DIR_LOCK) before changing the process working directory in tests. If the thread previously holding that mutex panicked while holding the lock, the Mutex is poisoned and .lock() returns Err, which this .expect turns into the 'current-dir test lock poisoned' panic.","triggerScenarios":"A test that panicked while inside CurrentDirGuard (holding the lock), followed by another test calling enter() in the same process.","commonSituations":"Test suites where an earlier test panicked mid-guard (e.g. set_current_dir failed or an assertion inside the guarded section), causing all subsequent current-dir-sensitive tests to fail with the poison message.","solutions":["Fix the underlying panic in the earlier test that poisoned the lock; this message is secondary.","Run tests with --test-threads=1 or isolate the offending test to identify the original panic.","Avoid panicking while the guard is held; use scopeguard/cleanup that restores the directory even on failure.","For resilience, recover from poisoning with lock().unwrap_or_else(|e| e.into_inner()) if the critical section is exception-safe."],"exampleFix":"// before\nlet lock = CURRENT_DIR_LOCK.get_or_init(|| Mutex::new(())).lock().expect(\"current-dir test lock poisoned\");\n// after\nlet lock = CURRENT_DIR_LOCK.get_or_init(|| Mutex::new(()))\n    .lock()\n    .unwrap_or_else(|poisoned| poisoned.into_inner()); // prior dir panic must not block later tests","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"let lock = CURRENT_DIR_LOCK.get_or_init(|| Mutex::new(()))\n    .lock()\n    .unwrap_or_else(|p| p.into_inner()); // recover from a previous test panic","preventionTips":["Fix the original panic that poisoned the lock; this error is secondary","Restore the working directory in Drop/scopeguard so panics can't leave state dirty","Run flaky suites with --test-threads=1 to isolate poison cascades","Recover via into_inner() only if the guarded section is exception-safe"],"tags":["rust","testing","mutex-poisoned"],"backgroundTag":"mutex-poisoned","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}