zellij-org/zellij · error
cannot acquire poisoned lock
Error message
cannot acquire poisoned lock
What it means
The non-DEBUG_MODE variant of the PoisonError ToAnyhow impl in zellij-utils/src/errors.rs: acquiring a std::sync::Mutex failed because a previous thread panicked while holding it, and the PoisonError details are suppressed in production builds. Like the debug variant it is a downstream symptom of an earlier panic in a critical section.
Source
Thrown at zellij-utils/src/errors.rs:988
.with_context(|| context.to_string())
} else {
Err(anyhow::anyhow!("failed to send message to channel"))
.with_context(|| context.to_string())
}
},
}
}
}
impl<U> ToAnyhow<U> for Result<U, std::sync::PoisonError<U>> {
fn to_anyhow(self) -> anyhow::Result<U> {
match self {
Ok(val) => anyhow::Ok(val),
Err(e) => {
if *crate::consts::DEBUG_MODE.get().unwrap_or(&true) {
Err(anyhow::anyhow!("cannot acquire poisoned lock for {e:#?}"))
} else {
Err(anyhow::anyhow!("cannot acquire poisoned lock"))
}
},
}
}
}
}
View on GitHub (pinned to bf8d23a4f7)
Solutions
- Enable DEBUG_MODE and reproduce to get variant [70] plus richer panic output.
- Kill the wedged session (zellij kill-session) and start fresh; in-process recovery from poisoning is not attempted.
- Report the ORIGINAL panic (first backtrace in the log) upstream with steps to reproduce.
- Update zellij.
Defensive patterns
Strategy: fallback
Try / catch
// non-debug build: same recovery decision, message is generic
let guard = mutex.lock().unwrap_or_else(|poisoned| {
log::error!("lock poisoned (earlier panic elsewhere); continuing with recovered state");
poisoned.into_inner()
}); Prevention
- Reproduce with DEBUG_MODE enabled to see the PoisonError detail of variant [70] and locate the poisoning thread.
- Keep panics out of locked regions so poisoning cannot occur in the first place.
- Consider parking_lot locks (no poisoning) in your own daemons, or catch_unwind around risky critical sections.
When it happens
Trigger: .lock().to_anyhow() (or the codebase's ToAnyhow combinators around it) on a mutex already flagged poisoned by an earlier panic in another thread, with DEBUG_MODE disabled so only the generic message appears.
Common situations: Production/default builds where a worker thread panicked and the session subsequently deadlocks or errors on every shared-state access; users see frozen UI and this message in logs.
Related errors
- cannot acquire poisoned lock for {e:#?}
- Invalid BareKey value: {}
- Invalid KeyModifier value: {}
- failed to load plugin from disk
- Failed to find pane {pane_id:?}
AI-assisted analysis of zellij-org/zellij@bf8d23a4f7 (2026-08-19).
Data as JSON: /api/errors/ee721a4c6a0eec9d.
Report an issue: GitHub.