{"record":{"id":"d726038f75e77cdf","repo":"atuinsh/atuin","slug":"default-socket-path-always-has-a-parent","errorCode":null,"errorMessage":"default socket path always has a parent","messagePattern":"default socket path always has a parent","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/atuin-client/src/settings/daemon.rs","lineNumber":230,"sourceCode":"#[cfg(unix)]\npub enum SocketPath<'a> {\n    /// A socket path that the user has manually configured in config.toml.\n    UserDefined(&'a Path),\n    /// The default socket path, used when the path is not manually set in config.toml.\n    Default(PathBuf),\n}\n\n#[cfg(unix)]\nimpl<'a> SocketPath<'a> {\n    /// Create the default socket directory if needed.\n    ///\n    /// This only applies to the default socket path: the directory holding a user-specified path\n    /// from config.toml is the user's to create, and `$XDG_RUNTIME_DIR` is created for us.\n    pub fn create_default_dir_if_needed(&self) -> Result<(), SecureTempDirError> {\n        let Self::Default(path) = self else {\n            return Ok(());\n        };\n        let dir = path.parent().expect(\"default socket path always has a parent\");\n        create_secure_temp_dir(dir)?;\n        Ok(())\n    }\n\n    #[must_use]\n    pub fn as_path(&self) -> &Path {\n        match self {\n            Self::UserDefined(path) => path,\n            Self::Default(path) => path,\n        }\n    }\n\n    #[must_use]\n    pub fn into_cow(self) -> Cow<'a, Path> {\n        match self {\n            Self::UserDefined(path) => path.into(),\n            Self::Default(path) => path.into(),\n        }","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/atuinsh/atuin/blob/900007c48045867e7f44b0f9bc55ad9dbe99ee0d/crates/atuin-client/src/settings/daemon.rs#L212-L248","documentation":"`create_default_dir_if_needed` takes the parent of the default socket path and asserts via `.expect(\"default socket path always has a parent\")` that a parent exists. Default socket paths are built as `<dir>/<file>` so a parent always exists; the panic would only fire if the path were a bare root or malformed. Note this only applies to the default variant — user-specified config paths are the user's responsibility.","triggerScenarios":"Calling `create_default_dir_if_needed` on a `SocketPath::Default` whose inner path has no parent (e.g. the path was constructed as just a filename or root \"/\").","commonSituations":"Practically unreachable with shipped defaults; can surface if the default socket path construction changes, or if tests construct `SocketPath::Default` from a bare relative filename.","solutions":["Check how the default socket path is built and ensure it includes a directory component","In tests, construct `SocketPath::Default` with an absolute path like /tmp/atuin.sock rather than a bare filename","Replace the expect with a guard returning SecureTempDirError if defensive behavior is desired"],"exampleFix":"// before\nlet dir = path.parent().expect(\"default socket path always has a parent\");\n// after\nlet Some(dir) = path.parent() else { return Ok(()); };","handlingStrategy":"validation","validationCode":"fn is_valid_default_socket_path(p: &Path) -> bool { p.parent().is_some() && p.file_name().is_some() }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always construct SocketPath::Default from absolute <dir>/<file> paths","Never build a default socket path from a bare filename","Test create_default_dir_if_needed with representative default paths"],"tags":["panic","invariant","filesystem","socket-path"],"backgroundTag":"internal-invariant-violation","analyzedSha":"900007c48045867e7f44b0f9bc55ad9dbe99ee0d","analyzedAt":"2026-09-19T12:52:51.491Z","contentChangedAt":"2026-09-19T12:52:51.491Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}