affaan-m/ECC · warning

current-dir test lock poisoned

Error message

current-dir test lock poisoned

What it means

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.

Solutions

  1. Fix the underlying panic in the earlier test that poisoned the lock; this message is secondary.
  2. Run tests with --test-threads=1 or isolate the offending test to identify the original panic.
  3. Avoid panicking while the guard is held; use scopeguard/cleanup that restores the directory even on failure.
  4. For resilience, recover from poisoning with lock().unwrap_or_else(|e| e.into_inner()) if the critical section is exception-safe.

Example fix

// before
let lock = CURRENT_DIR_LOCK.get_or_init(|| Mutex::new(())).lock().expect("current-dir test lock poisoned");
// after
let lock = CURRENT_DIR_LOCK.get_or_init(|| Mutex::new(()))
    .lock()
    .unwrap_or_else(|poisoned| poisoned.into_inner()); // prior dir panic must not block later tests
Defensive patterns

Strategy: fallback

Try / catch

let lock = CURRENT_DIR_LOCK.get_or_init(|| Mutex::new(()))
    .lock()
    .unwrap_or_else(|p| p.into_inner()); // recover from a previous test panic

Prevention

When it happens

Trigger: A test that panicked while inside CurrentDirGuard (holding the lock), followed by another test calling enter() in the same process.

Common situations: 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.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/85ab67683aeabeef. Report an issue: GitHub.

Appendix: source

Thrown at ecc2/src/main.rs:28

#[cfg(test)]
pub(crate) mod test_support {
    use anyhow::{Context, Result};
    use std::path::{Path, PathBuf};
    use std::sync::{Mutex, MutexGuard, OnceLock};

    static CURRENT_DIR_LOCK: OnceLock<Mutex<()>> = OnceLock::new();

    pub(crate) struct CurrentDirGuard {
        _lock: MutexGuard<'static, ()>,
        original_dir: PathBuf,
    }

    impl CurrentDirGuard {
        pub(crate) fn enter(target_dir: &Path) -> Result<Self> {
            let lock = CURRENT_DIR_LOCK
                .get_or_init(|| Mutex::new(()))
                .lock()
                .expect("current-dir test lock poisoned");
            let original_dir =
                std::env::current_dir().context("Failed to capture current test directory")?;
            std::env::set_current_dir(target_dir).with_context(|| {
                format!("Failed to enter test directory {}", target_dir.display())
            })?;

            Ok(Self {
                _lock: lock,
                original_dir,
            })
        }
    }

    impl Drop for CurrentDirGuard {
        fn drop(&mut self) {
            let _ = std::env::set_current_dir(&self.original_dir);
        }
    }

View on GitHub (pinned to 8321021c54)