niri-wm/niri · error · io::Error
io::ErrorKind::NotFound
io::ErrorKind::NotFound
Error message
NIRI_SOCKET is not set, are you running this within niri?
What it means
niri-ipc's Socket::connect() reads the socket path from the NIRI_SOCKET environment variable — niri exports it to every process it spawns (terminals, app launchers). The variable is unset, so connect() fails fast with ErrorKind::NotFound before any socket is opened: the caller is not running as a descendant of a niri session. The message is a hint ('are you running this within niri?'), not a permission or socket problem.
Source
Thrown at niri-ipc/src/socket.rs:29
/// Name of the environment variable containing the niri IPC socket path.
pub const SOCKET_PATH_ENV: &str = "NIRI_SOCKET";
/// Helper for blocking communication over the niri socket.
///
/// This struct is used to communicate with the niri IPC server. It handles the socket connection
/// and serialization/deserialization of messages.
pub struct Socket {
stream: BufReader<UnixStream>,
}
impl Socket {
/// Connects to the default niri IPC socket.
///
/// This is equivalent to calling [`Self::connect_to`] with the path taken from the
/// [`SOCKET_PATH_ENV`] environment variable.
pub fn connect() -> io::Result<Self> {
let socket_path = env::var_os(SOCKET_PATH_ENV).ok_or_else(|| {
io::Error::new(
io::ErrorKind::NotFound,
format!("{SOCKET_PATH_ENV} is not set, are you running this within niri?"),
)
})?;
Self::connect_to(socket_path)
}
/// Connects to the niri IPC socket at the given path.
pub fn connect_to(path: impl AsRef<Path>) -> io::Result<Self> {
let stream = UnixStream::connect(path.as_ref())?;
let stream = BufReader::new(stream);
Ok(Self { stream })
}
/// Sends a request to niri and returns the response.
///
/// Return values:
///View on GitHub (pinned to 606284464d)
Solutions
- Run the command from a terminal launched inside niri (it inherits NIRI_SOCKET); that is the supported path.
- Set the variable manually for out-of-session contexts: NIRI_SOCKET=$XDG_RUNTIME_DIR/niri.wayland-1 niri msg ... (check the actual path with 'ls $XDG_RUNTIME_DIR | grep niri' from inside the session).
- For systemd user units, import the variable: add 'PassEnvironment=NIRI_SOCKET' style plumbing or read the path in an EnvironmentFile written at login.
- If the goal is automation from outside, connect_to(path) directly with the discovered socket path instead of connect().
Example fix
# before: no inherited session environment ssh host 'niri msg action focus-column-right' # error: NIRI_SOCKET is not set, are you running this within niri? # after: point the client at the session socket explicitly ssh host 'NIRI_SOCKET=/run/user/1000/niri.wayland-1 niri msg action focus-column-right'
Defensive patterns
Strategy: validation
Validate before calling
// Rust (niri-ipc): check the env var and a fallback path before connecting
let path = std::env::var_os("NIRI_SOCKET")
.or_else(|| {
let p = std::env::temp_dir().join(format!("niri.{}.wayland-1", uid));
p.exists().then_some(p.into_os_string())
})
.ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "not running inside niri"))?;
let socket = Socket::connect_to(path)?; Type guard
fn is_running_under_niri() -> bool {
std::env::var_os("NIRI_SOCKET").is_some()
} Try / catch
match Socket::connect() {
Ok(s) => s,
Err(e) if e.kind() == io::ErrorKind::NotFound => {
// not an IPC failure: we are outside the niri session
eprintln!("NIRI_SOCKET is not set; run this inside niri or connect_to() the socket in $XDG_RUNTIME_DIR");
std::process::exit(2);
}
Err(e) => return Err(e.into()),
} Prevention
- Run IPC clients from terminals spawned by niri; they inherit NIRI_SOCKET.
- For out-of-session automation, export NIRI_SOCKET=$XDG_RUNTIME_DIR/niri.wayland-1 explicitly.
- Distinguish NotFound (env missing) from PermissionDenied (wrong user) before debugging further.
- In systemd units, pass the variable through PassEnvironment/EnvironmentFile captured at login.
When it happens
Trigger: Running 'niri msg ...' (or any niri-ipc client calling Socket::connect()) from a context that did not inherit niri's environment: SSH login, systemd user service unit, cron, another compositor, or a shell started before niri.
Common situations: Remoting in via SSH and trying to control the local niri; scripts wired to systemd user timers/services or udev rules where NIRI_SOCKET is not in the environment; launching niri msg from a new login after niri was started elsewhere; using niri-ipc in a test harness outside the session.
Related errors
AI-assisted analysis of niri-wm/niri@606284464d (2026-08-16).
Data as JSON: /api/errors/2b6dd16dcb6c7789.
Report an issue: GitHub.