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
- 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.
- Discover valid targets before acting: 'niri msg outputs', 'niri msg workspaces', 'niri msg windows' and use those exact names/ids in the command.
- 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.
- 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
- Discover-then-act: always list outputs/windows/workspaces first and feed exact names/ids into the action.
- Restart niri and niri msg together after upgrades so the IPC schema matches.
- Treat err_msg as authoritative input for scripts; do not parse the outer 'niri returned an error' wrapper.
- Guard automation with existence checks (niri msg windows | grep id) to avoid races with closing windows.
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.