{"record":{"id":"3f38abe8c44fc22c","repo":"SeaQL/sea-orm","slug":"failed-to-acquire-mocker","errorCode":null,"errorMessage":"Failed to acquire mocker","messagePattern":"Failed to acquire mocker","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sea-orm-sync/src/driver/mock.rs","lineNumber":208,"sourceCode":"        #[cfg(feature = \"sync\")]\n        {\n            match self.query_all(statement.clone()) {\n                Ok(v) => Box::new(v.into_iter().map(Ok)),\n                Err(e) => Box::new(Some(Err(e)).into_iter()),\n            }\n        }\n    }\n\n    /// Create a statement block  of SQL statements that execute together.\n    ///\n    /// # Panics\n    ///\n    /// Will panic if the lock cannot be acquired.\n    #[instrument(level = \"trace\")]\n    pub fn begin(&self) {\n        self.mocker\n            .lock()\n            .expect(\"Failed to acquire mocker\")\n            .begin()\n    }\n\n    /// Commit a transaction atomically to the database\n    ///\n    /// # Panics\n    ///\n    /// Will panic if the lock cannot be acquired.\n    #[instrument(level = \"trace\")]\n    pub fn commit(&self) {\n        self.mocker\n            .lock()\n            .expect(\"Failed to acquire mocker\")\n            .commit()\n    }\n\n    /// Roll back a faulty transaction\n    ///","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/SeaQL/sea-orm/blob/e29bcd1b417c41a553b386fe94511d7c64a1c8ec/sea-orm-sync/src/driver/mock.rs#L190-L226","documentation":"`MockDatabaseConnection::begin` locks the mocker mutex and panics with \"Failed to acquire mocker\" if the lock is poisoned (a prior panic occurred while another thread held it). Transaction begin on the mock backend cannot return an error, so the library escalates lock poisoning to a hard panic. Functionally identical to error 67 but on the transaction-begin path.","triggerScenarios":"Beginning a transaction (`Database::begin` / `db.begin()`) against a mock-backed connection whose `Mutex<Box<dyn MockDatabaseTrait>>` was poisoned by an earlier panic, or attempting reentrant lock acquisition from code already holding the mocker lock (e.g. inside a mock callback that calls `begin`).","commonSituations":"Typical in test suites: a panicking mock expectation or an earlier test failure poisons the shared mock connection; the next `db.begin()` panics with this message instead of failing the test cleanly. Also seen with mock connections shared across async tasks run on multiple threads.","solutions":["Find and fix the first panic in the run — it poisoned the mocker lock; later \"Failed to acquire mocker\" panics are secondary.","Don't call back into the connection (begin/commit/execute) from inside `MockDatabaseTrait` callbacks to avoid reentrant locking.","Give each test its own `MockDatabase`/connection instead of sharing one across tests or threads.","Recover defensively with `lock().unwrap_or_else(|p| p.into_inner())` if a poisoned-but-usable mocker is acceptable in your harness.","Return errors from mock logic rather than panicking, so the lock is released cleanly."],"exampleFix":"// before\npub fn begin(&self) {\n    self.mocker.lock().expect(\"Failed to acquire mocker\").begin()\n}\n// after\npub fn begin(&self) {\n    self.mocker\n        .lock()\n        .unwrap_or_else(|poisoned| poisoned.into_inner())\n        .begin()\n}","handlingStrategy":"type-guard","validationCode":"// Only begin a mock transaction when the mocker lock is healthy\nif conn.get_mocker_mutex().is_poisoned() {\n    eprintln!(\"mock connection poisoned; recreating before begin()\");\n    conn = recreate_mock_connection();\n}","typeGuard":"fn can_begin_mock_txn(conn: &MockDatabaseConnection) -> bool {\n    !conn.get_mocker_mutex().is_poisoned()\n}","tryCatchPattern":"std::panic::catch_unwind(AssertUnwindSafe(|| txn.begin()))\n    .unwrap_or_else(|_| {\n        eprintln!(\"begin() panicked on poisoned mocker; building a new mock db\");\n        // fall back to a fresh DatabaseConnection over a new MockDatabase\n    });","preventionTips":["Locate and fix the first panic in the run; the poisoned lock is a downstream effect","One MockDatabase per test — never share mock connections across tests or threads","Do not invoke begin/commit from inside mock callbacks","Prefer returning errors from mock logic over panicking while holding the lock","Consider lock().unwrap_or_else(PoisonError::into_inner) in custom wrappers"],"tags":["panic","mutex-poisoned","mock","transaction","testing"],"backgroundTag":"internal-invariant-violation","analyzedSha":"e29bcd1b417c41a553b386fe94511d7c64a1c8ec","analyzedAt":"2026-09-10T11:31:52.468Z","contentChangedAt":"2026-09-10T11:31:52.468Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}