{"record":{"id":"75f5ee814674c970","repo":"mgth/LittleBigMouse","slug":"notfound-no-per-user-runtime-directory","errorCode":"NotFound","errorMessage":"no per-user runtime directory","messagePattern":"no per-user runtime directory","errorType":"error_code","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"rust/crates/lbm-hook/src/ipc/server.rs","lineNumber":458,"sourceCode":"\n        pub async fn run(self, server: ServerHandle, _shared: &'static Shared) {\n            let semaphore = Arc::new(Semaphore::new(MAX_CLIENTS));\n            while let Ok((stream, _)) = self.listener.accept().await {\n                let Ok(permit) = semaphore.clone().try_acquire_owned() else {\n                    continue;\n                };\n                tokio::spawn(run_connection(stream, server.clone(), permit));\n            }\n            let _ = std::fs::remove_file(&self.path);\n        }\n    }\n\n    pub fn default_endpoint() -> io::Result<String> {\n        let runtime = std::env::var_os(\"XDG_RUNTIME_DIR\").map(PathBuf::from);\n        let data = crate::platform::paths::lbm_data_file(\"\");\n        lbm_ipc::endpoint::socket_path(runtime.as_deref(), data.as_deref())\n            .map(|path| path.to_string_lossy().into_owned())\n            .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, \"no per-user runtime directory\"))\n    }\n}\n","sourceCodeStart":440,"sourceCodeEnd":461,"githubUrl":"https://github.com/mgth/LittleBigMouse/blob/7a42f01d47d99d223b8ee33ba4019af82adf1c48/rust/crates/lbm-hook/src/ipc/server.rs#L440-L461","documentation":"default_endpoint() builds the IPC socket path by asking lbm_ipc::endpoint::socket_path to pick between XDG_RUNTIME_DIR and the fallback data directory. When neither yields a usable per-user path, it returns NotFound with \"no per-user runtime directory\". The IPC server cannot be started or located without a valid socket path.","triggerScenarios":"Calling default_endpoint() when the XDG_RUNTIME_DIR environment variable is unset/empty AND the fallback lbm_data_file(\"\") path is also unavailable (e.g. socket_path returned None), so there is no writable per-user directory to place the Unix domain socket.","commonSituations":"Running the daemon from a systemd unit or cron job with a minimal environment where XDG_RUNTIME_DIR is not exported; su/sudo dropping the env var; non-standard login shells; running as a system user with no XDG session and unwritable data dir.","solutions":["Ensure XDG_RUNTIME_DIR is set, e.g. export XDG_RUNTIME_DIR=/run/user/$(id -u) before launching the daemon/service.","In systemd units add Environment=XDG_RUNTIME_DIR=/run/user/%U (or use ExecStart with a user session slice so the variable is inherited).","If relying on the fallback, make sure the lbm data directory exists and is writable by the current user.","Pre-create the runtime directory with correct ownership: install -d -m 700 -o $USER /run/user/$(id -u)."],"exampleFix":"# before (fails in systemd unit)\nExecStart=/usr/bin/littlebigmouse\n# after\nExecStart=/usr/bin/littlebigmouse\nEnvironment=XDG_RUNTIME_DIR=/run/user/%U","handlingStrategy":"validation","validationCode":"// before starting the IPC server\nif std::env::var_os(\"XDG_RUNTIME_DIR\").map(|v| v.is_empty()).unwrap_or(true) {\n    std::env::set_var(\"XDG_RUNTIME_DIR\", format!(\"/run/user/{}\", nix::unistd::getuid()));\n}","typeGuard":null,"tryCatchPattern":"match default_endpoint() {\n    Ok(ep) => listen(ep),\n    Err(e) if e.kind() == std::io::ErrorKind::NotFound => {\n        eprintln!(\"XDG_RUNTIME_DIR missing; set it to /run/user/$UID\");\n        std::process::exit(1);\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["In systemd units, always set Environment=XDG_RUNTIME_DIR=/run/user/%U.","Never launch daemons via bare `sudo` (which strips env); use sudo -E or systemd user services.","Assert the runtime dir exists and is writable at startup, before creating the socket."],"tags":["ipc","linux","xdg","environment-variable","unix-socket"],"backgroundTag":"missing-env-var","analyzedSha":"7a42f01d47d99d223b8ee33ba4019af82adf1c48","analyzedAt":"2026-09-16T00:35:00.514Z","contentChangedAt":"2026-09-16T00:35:00.514Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}