LGUG2Z/komorebi · critical
could not subscribe to komorebi notifications
Error message
could not subscribe to komorebi notifications
What it means
komorebi-client's subscribe_with_options connects to komorebi's named-pipe notification broker and returns a SocketListener. This panic fires when the client fails to create or connect the subscription socket, meaning the bar cannot receive window-manager state updates. It is an expect() in a spawned thread, so the whole process aborts when the handshake fails.
Source
Thrown at komorebi-bar/src/main.rs:350
eframe::run_native(
"komorebi-bar",
native_options,
Box::new(|cc| {
let ctx_repainter = cc.egui_ctx.clone();
std::thread::spawn(move || loop {
std::thread::sleep(Duration::from_secs(1));
ctx_repainter.request_repaint();
});
let ctx_komorebi = cc.egui_ctx.clone();
std::thread::spawn(move || {
let subscriber_name = format!("komorebi-bar-{}", random_word::get(random_word::Lang::En));
let listener = komorebi_client::subscribe_with_options(&subscriber_name, SubscribeOptions {
filter_state_changes: true,
})
.expect("could not subscribe to komorebi notifications");
tracing::info!("subscribed to komorebi notifications: \"{}\"", subscriber_name);
for client in listener.incoming() {
match client {
Ok(subscription) => {
match subscription.set_read_timeout(Some(Duration::from_secs(1))) {
Ok(()) => {}
Err(error) => tracing::error!("{}", error),
}
let mut buffer = Vec::new();
let mut reader = BufReader::new(subscription);
// this is when we know a shutdown has been sent
if matches!(reader.read_to_end(&mut buffer), Ok(0)) {
tracing::info!("disconnected from komorebi");
// keep trying to reconnect to komorebiView on GitHub (pinned to e0709f02bf)
Solutions
- Ensure komorebi is running and healthy before launching komorebi-bar (start bar after komorebi, or add a wait/retry loop around subscribe_with_options)
- Check that no stale komorebi subscription sockets/named pipes exist from a previous crashed session; restart komorebi to recreate them
- Verify komorebi and komorebi-bar versions match (komorebi-client talks a specific protocol); update both together
- Run komorebi-bar in the same user session as komorebi so the pipe is accessible (no cross-session/permission mismatch)
- If appropriate for the bar, replace expect with a loop that retries the subscription after a delay and logs the failure instead of panicking
Example fix
// before
let listener = komorebi_client::subscribe_with_options(&subscriber_name, SubscribeOptions {
filter_state_changes: true,
})
.expect("could not subscribe to komorebi notifications");
// after
let listener = loop {
match komorebi_client::subscribe_with_options(&subscriber_name, SubscribeOptions {
filter_state_changes: true,
}) {
Ok(l) => break l,
Err(e) => {
tracing::warn!("could not subscribe to komorebi notifications ({e}); retrying in 2s");
std::thread::sleep(std::time::Duration::from_secs(2));
}
}
}; Defensive patterns
Strategy: retry
Validate before calling
// Rust: check komorebi socket reachability before subscribing
fn komorebi_running() -> bool {
std::process::Command::new("tasklist")
.args(["/FI", "IMAGENAME eq komorebi.exe"])
.output()
.map(|o| String::from_utf8_lossy(&o.stdout).contains("komorebi.exe"))
.unwrap_or(false)
}
if !komorebi_running() { eprintln!("komorebi not running; defer bar start"); } Try / catch
loop {
match komorebi_client::subscribe_with_options(&name, opts) {
Ok(l) => break l,
Err(e) => { log::warn!("subscribe failed: {e}"); std::thread::sleep(Duration::from_secs(2)); }
}
} Prevention
- Start komorebi-bar only after komorebi is fully running (startup dependency ordering)
- Wrap subscription in a bounded retry with backoff instead of expect
- Pin komorebi and komorebi-bar to matching versions
- Clean up stale named pipes after crashes before restarting
When it happens
Trigger: Calling komorebi_client::subscribe_with_options with SubscribeOptions { filter_state_changes: true } when the komorebi broker/socket is unreachable: komorebi is not running, the pipe path is wrong, the subscription name cannot be registered, or a previous subscriber left a stale socket.
Common situations: Starting komorebi-bar at login before komorebi has initialized its socket; komorebi crashed while the bar auto-restarts; running komorebi-bar outside a komorebi-managed session (e.g. testing on a machine without komorebi running); permission issues on the named pipe.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- no home directory found
- there is no home directory
- $Env:KOMOREBI_CONFIG_HOME is set to '{home_path}', which is
- unable to get exec path
- there is no local data directory
AI-assisted analysis of LGUG2Z/komorebi@e0709f02bf (2026-09-06).
Data as JSON: /api/errors/77965f466fe85ca0.
Report an issue: GitHub.