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

  1. Enable DEBUG_MODE and reproduce to get variant [70] plus richer panic output.
  2. Kill the wedged session (zellij kill-session) and start fresh; in-process recovery from poisoning is not attempted.
  3. Report the ORIGINAL panic (first backtrace in the log) upstream with steps to reproduce.
  4. 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

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


AI-assisted analysis of zellij-org/zellij@bf8d23a4f7 (2026-08-19). Data as JSON: /api/errors/ee721a4c6a0eec9d. Report an issue: GitHub.