niri-wm/niri · error · anyhow::Error

niri returned an error

Error message

niri returned an error

What it means

niri's IPC client (niri msg / niri-ipc) sends a request over the Unix socket and the compositor replies either with a payload or an error string. This message is the client-side wrapper: the reply was an error response, and err_msg contains the compositor's reason (e.g. 'no such output', 'invalid value'). It means the connection worked and the protocol was understood — the request itself was rejected.

Source

Thrown at src/ipc/client.rs:111

                eprintln!("Compositor version: {compositor_version}");
                eprintln!("CLI version:        {cli_version}");
                eprintln!("Did you forget to restart niri after an update?");
                eprintln!();
            }
        }
        Some(_) => {
            eprintln!("Unable to get the running niri compositor version.");
            eprintln!("Did you forget to restart niri after an update?");
            eprintln!();
        }
        None => {
            // Communication error, or the original request was already a version request, or the
            // original request had succeeded. Don't add irrelevant context.
        }
    }

    let reply = result.context("error communicating with niri")?;
    let response = reply.map_err(|err_msg| anyhow!(err_msg).context("niri returned an error"))?;

    match msg {
        Msg::RequestError => {
            bail!("unexpected response: expected an error, got {response:?}");
        }
        Msg::Version => {
            let Response::Version(compositor_version) = response else {
                bail!("unexpected response: expected Version, got {response:?}");
            };

            let cli_version = version();

            if json {
                println!(
                    "{}",
                    json!({
                        "compositor": compositor_version,
                        "cli": cli_version,

View on GitHub (pinned to 606284464d)

Solutions

  1. Read err_msg in the error chain — it names the exact reason ('unknown output', 'no window with id', etc.) and points at the offending argument.
  2. Discover valid targets before acting: 'niri msg outputs', 'niri msg workspaces', 'niri msg windows' and use those exact names/ids in the command.
  3. After upgrading niri, restart the compositor so the running server and the niri msg client match; the 'Did you forget to restart niri after an update?' hint from the version check indicates exactly this.
  4. In scripts, re-query ids immediately before using them and tolerate failure (the window may have closed between listing and acting).

Example fix

# before: output name guessed, compositor rejects it
niri msg output focus HDMI-1
# niri returned an error: unknown output: HDMI-1

# after: list real outputs first, then use the exact name
niri msg outputs
niri msg output focus DP-1
Defensive patterns

Strategy: try-catch

Validate before calling

# shell: validate targets before sending the request
niri msg outputs | grep -q "^Output \"DP-1\"" || { echo "no such output" >&2; exit 1; }
niri msg output DP-1 focus

Try / catch

// Rust (niri-ipc client): distinguish rejection from transport failure and show the server's reason
match ipc.send(msg).await {
    Err(e) => return Err(e.context("error communicating with niri")),
    Ok(Reply::Err(reason)) => {
        eprintln!("niri rejected the request: {reason}");
        // optionally re-query state (outputs/windows) and retry once with corrected args
        std::process::exit(1);
    }
    Ok(Reply::Ok(resp)) => resp,
}

Prevention

When it happens

Trigger: Any niri msg action the compositor refuses: focusing or moving a workspace to a nonexistent output, referencing a window/workspace by an id that no longer exists, an unknown action name (version skew between CLI and running compositor), or invalid arguments to actions like set-window-width.

Common situations: Scripts hardcoding output names (eDP-1 vs DP-1) after re-docking; racing a window close (window id gone by the time the command runs); running a newer/older niri msg binary against a compositor started before/after an update (IPC schema mismatch); typos in action names in config binds or shell scripts.

Related errors


AI-assisted analysis of niri-wm/niri@606284464d (2026-08-16). Data as JSON: /api/errors/59f92bc162f38501. Report an issue: GitHub.