SeaQL/sea-orm · error

Failed to acquire mocker

Error message

Failed to acquire mocker

What it means

MockTransaction (or MockDatabase) begin() locks the mocker mutex with expect("Failed to acquire mocker"). A poisoned mutex — caused by a panic in another thread while the lock was held — makes lock() return Err and this expect panics. The mocked transaction cannot even be started.

Source

Thrown at src/driver/mock.rs:209

        #[cfg(feature = "sync")]
        {
            match self.query_all(statement.clone()) {
                Ok(v) => Box::new(v.into_iter().map(Ok)),
                Err(e) => Box::new(Some(Err(e)).into_iter()),
            }
        }
    }

    /// Create a statement block  of SQL statements that execute together.
    ///
    /// # Panics
    ///
    /// Will panic if the lock cannot be acquired.
    #[instrument(level = "trace")]
    pub fn begin(&self) {
        self.mocker
            .lock()
            .expect("Failed to acquire mocker")
            .begin()
    }

    /// Commit a transaction atomically to the database
    ///
    /// # Panics
    ///
    /// Will panic if the lock cannot be acquired.
    #[instrument(level = "trace")]
    pub fn commit(&self) {
        self.mocker
            .lock()
            .expect("Failed to acquire mocker")
            .commit()
    }

    /// Roll back a faulty transaction
    ///

View on GitHub (pinned to e29bcd1b41)

Solutions

  1. Diagnose and fix the root panic that poisoned the mutex (run the offending test alone to see its original panic).
  2. Isolate tests: one MockDatabase per test, no shared connector across threads.
  3. Recover from poisoning via lock().unwrap_or_else(|p| p.into_inner()) if shared state remains consistent.
  4. Make mock callbacks return Result instead of panicking on unexpected statements.

Example fix

// before
self.mocker.lock().expect("Failed to acquire mocker").begin()
// after
self.mocker.lock().unwrap_or_else(|poisoned| poisoned.into_inner()).begin()
Defensive patterns

Strategy: validation

Validate before calling

// Guard before begin():
if connector.mocker.is_poisoned() { panic!("fixture corrupted by earlier panic; recreate MockDatabase"); }

Type guard

fn can_begin(c: &MockDatabaseConnector) -> bool { !c.mocker.is_poisoned() }

Try / catch

std::panic::catch_unwind(AssertUnwindSafe(|| txn.begin()))
    .unwrap_or_else(|_| recreate_mock_and_begin());

Prevention

When it happens

Trigger: Calling begin() on a mock transaction after a prior panic occurred while another thread held the mocker lock (e.g. a mock callback asserted on unexpected SQL and panicked).

Common situations: Test suites running mocked DB operations concurrently on a shared connector; one failing test poisons the lock and cascades 'Failed to acquire mocker' panics into all later tests.

Related errors


AI-assisted analysis of SeaQL/sea-orm@e29bcd1b41 (2026-09-10). Data as JSON: /api/errors/55407df8b68792e0. Report an issue: GitHub.