t8y2/dbx · error
driver operation lock table poisoned
Error message
driver operation lock table poisoned
What it means
driver_operation_lock acquires the process-wide driver_operation_locks table guarded by a std::sync::Mutex. .lock() returns Err (poisoned) if another thread panicked while holding the mutex; the expect("driver operation lock table poisoned") then panics in turn. It signals that some earlier driver-operation code path panicked while mutating the lock table.
Source
Thrown at crates/dbx-core/src/agent_service.rs:893
progress(AgentProgressEvent::step("all-done"));
Ok(result)
}
fn is_cancelled_error(error: &str) -> bool {
error.contains(AGENT_DOWNLOAD_CANCELED_ERROR)
}
async fn can_fallback_to_local_agent(
_am: &AgentManager,
_db_type: &str,
cancellations: &[&AgentInstallCancellation],
) -> bool {
!cancellations.iter().any(|token| token.is_cancelled())
}
fn driver_operation_lock<'a>(am: &'a AgentManager, db_type: &str) -> OperationLockHandle<'a> {
let mut locks = am.driver_operation_locks.lock().expect("driver operation lock table poisoned");
let lock = locks.entry(db_type.to_string()).or_insert_with(|| Arc::new(tokio::sync::Mutex::new(()))).clone();
OperationLockHandle::new(&am.driver_operation_locks, db_type, lock)
}
fn jre_operation_lock<'a>(am: &'a AgentManager, jre_key: &str) -> OperationLockHandle<'a> {
let mut locks = am.jre_install_locks.lock().expect("JRE install lock table poisoned");
let lock = locks.entry(jre_key.to_string()).or_insert_with(|| Arc::new(tokio::sync::Mutex::new(()))).clone();
OperationLockHandle::new(&am.jre_install_locks, jre_key, lock)
}
/// Future that resolves as soon as any cancellation token fires.
fn first_cancellation<'a>(
cancellations: &'a [&'a AgentInstallCancellation],
) -> std::pin::Pin<Box<dyn std::future::Future<Output = ()> + Send + 'a>> {
Box::pin(async move {
let ((), _index, _rest) =
futures::future::select_all(cancellations.iter().map(|token| Box::pin(token.cancelled()))).await;
})View on GitHub (pinned to c0390bff16)
Solutions
- Find and fix the original panic that poisoned the mutex — the poisoned-guard payload usually contains it.
- If resilience is needed, use lock().unwrap_or_else(|p| p.into_inner()) to recover, since the table is just an entry map.
- Prefer scoped locking that avoids panicking while the guard is held (no expect/unwrap inside the critical section).
- Consider a parking_lot::Mutex (non-poisoning) for lock tables like this.
Example fix
// before
let mut locks = am.driver_operation_locks.lock().expect("driver operation lock table poisoned");
// after
let mut locks = am.driver_operation_locks.lock().unwrap_or_else(|poisoned| poisoned.into_inner()); Defensive patterns
Strategy: try-catch
Validate before calling
// detect poisoning early in health checks
if am.driver_operation_locks.is_poisoned() {
tracing::error!("driver_operation_locks mutex is poisoned; restart or recover");
} Type guard
fn lock_table_healthy(locks: &std::sync::Mutex<DriverLockTable>) -> bool {
!locks.is_poisoned()
} Try / catch
let mut locks = am.driver_operation_locks.lock().unwrap_or_else(|poisoned| {
tracing::warn!("driver lock table was poisoned; recovering: {:?}", poisoned);
poisoned.into_inner()
}); Prevention
- Never unwrap/expect/panic while holding a std Mutex guard.
- Return Result from code that mutates the lock table.
- Consider parking_lot::Mutex for non-poisoning semantics.
- Log the original panic payload from PoisonError to find the root cause fast.
When it happens
Trigger: Any driver operation (install_agent_driver_with_batch, uninstall_agent_driver, import_agent_driver, ensure_agent_driver_ready_from, install_agent_driver_from_registry_locked) panics while holding the driver_operation_locks mutex; the next caller of driver_operation_lock then hits the poisoned lock and panics.
Common situations: An earlier install/uninstall panicked (bug, assertion, failed expect like 1082) and left the mutex poisoned; subsequent operations that should work now cascade-fail; in tests this shows as an unexpected panic on the second operation after a deliberately panicking case.
Related errors
- JRE install lock table poisoned
- DBX_PUBLIC_BASE_PATH contains invalid characters
- error while building tauri application: {error}
- a batch cancellation token is always available
- driver token registered
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/a13da6aa8c5bdae0.
Report an issue: GitHub.