Skip to content

Command widget panics with std::sync::Mutex under WASMI (zellij 0.44.1) #247

Description

@enieuwy

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"
        }
    }
}
  1. Start a zellij session with this layout (6 tabs, session restored after reboot)
  2. Wait ~5 minutes, or trigger a client re-attach
  3. 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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions