Describe the bug
The command widget triggers a std::sync::Mutex panic inside zellij 0.44.1's WASMI interpreter. Once the panic occurs, the plugin instance is permanently corrupted — every subsequent render event produces out of bounds memory access errors, causing persistent "ERROR IN PLUGIN" flashing in the status bar.
Environment
- OS: macOS 26.4 (arm64, Apple M1 Max)
- Zellij: 0.44.1 (homebrew)
- zjstatus: v0.22.0 (SHA256
4de426d20b1cbf861272e927aeeb5b49d92c17f0e2bb9d173f85bf7f0154dd53)
- WASM runtime: WASMI interpreter (zellij 0.44.1 default)
To Reproduce
Layout with a command widget:
layout {
default_tab_template {
pane size=1 borderless=true {
plugin location="file:~/.config/zellij/plugins/zjstatus.wasm" {
command_ai_quota_command "~/.local/bin/ai-quota-zellij-bar-cache"
command_ai_quota_interval "30"
command_ai_quota_rendermode "raw"
format_left "{command_ai_quota}"
format_center ""
format_right ""
format_space ""
}
}
children
pane size=1 borderless=true {
plugin location="compact-bar"
}
}
}
- Start a zellij session with this layout (6 tabs, session restored after reboot)
- Wait ~5 minutes, or trigger a client re-attach
- Plugin crashes with
"ERROR IN PLUGIN - check logs for more info" flashing
Crash Sequence (from zellij log)
Session starts successfully at 22:50:33. Plugin loads fine:
INFO | Loaded plugin '/Users/ellis/.config/zellij/plugins/zjstatus.wasm' in 10.268083ms
~5 minutes later, on a client re-attach event at 22:55:42:
DEBUG | panicked at library/std/src/sys/sync/mutex/no_threads.rs:19:9:
DEBUG | thread panicked while processing panic. aborting.
Then cascading into:
ERROR | Failed to apply event to plugin 11
Caused by: wasm `unreachable` instruction executed
Followed by permanent out of bounds memory access on every subsequent render tick — once corrupted, the plugin instance never recovers.
Root Cause
The panic occurs at std::sync::Mutex initialization in no_threads.rs. The WASMI interpreter is single-threaded and does not support std::sync::Mutex. This suggests zjstatus is using a OnceLock<Mutex<...>> or similar pattern in the command widget's internal state management that hits this codepath during event processing.
The crash is triggered by client re-attach / layout re-evaluation, not by command output itself. The command being polled (ai-quota-zellij-bar-cache) runs fine independently and returns valid ANSI output.
Workaround
Switched from the command widget to a pipe widget, with an external process feeding zellij pipe "zjstatus::pipe::pipe_ai_quota::...". The pipe widget avoids the background command execution codepath and does not trigger the mutex panic.
plugin location="file:~/.config/zellij/plugins/zjstatus.wasm" {
pipe_ai_quota_format "{output}"
pipe_ai_quota_rendermode "raw"
format_left "{pipe_ai_quota}"
format_center ""
format_right ""
format_space ""
}
This has been stable — no crashes after the switch.
Related
Describe the bug
The
commandwidget triggers astd::sync::Mutexpanic inside zellij 0.44.1's WASMI interpreter. Once the panic occurs, the plugin instance is permanently corrupted — every subsequent render event producesout of bounds memory accesserrors, causing persistent "ERROR IN PLUGIN" flashing in the status bar.Environment
4de426d20b1cbf861272e927aeeb5b49d92c17f0e2bb9d173f85bf7f0154dd53)To Reproduce
Layout with a
commandwidget:"ERROR IN PLUGIN - check logs for more info"flashingCrash Sequence (from zellij log)
Session starts successfully at
22:50:33. Plugin loads fine:~5 minutes later, on a client re-attach event at
22:55:42:Then cascading into:
Followed by permanent
out of bounds memory accesson every subsequent render tick — once corrupted, the plugin instance never recovers.Root Cause
The panic occurs at
std::sync::Mutexinitialization inno_threads.rs. The WASMI interpreter is single-threaded and does not supportstd::sync::Mutex. This suggests zjstatus is using aOnceLock<Mutex<...>>or similar pattern in the command widget's internal state management that hits this codepath during event processing.The crash is triggered by client re-attach / layout re-evaluation, not by command output itself. The command being polled (
ai-quota-zellij-bar-cache) runs fine independently and returns valid ANSI output.Workaround
Switched from the
commandwidget to apipewidget, with an external process feedingzellij pipe "zjstatus::pipe::pipe_ai_quota::...". The pipe widget avoids the background command execution codepath and does not trigger the mutex panic.This has been stable — no crashes after the switch.
Related
std::thread::local::LocalKey)