{"record":{"id":"2cbe315e75b7b6b9","repo":"herdrdev/herdr","slug":"failed-to-create-private-herdr-ssh-config-director-2cbe31","errorCode":null,"errorMessage":"failed to create private herdr ssh config directory","messagePattern":"failed to create private herdr ssh config directory","errorType":"error_code","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"src/platform/fallback.rs","lineNumber":35,"sourceCode":"    super::RemoteSshConfigPaths {\n        user_config: std::env::var_os(\"HOME\")\n            .map(PathBuf::from)\n            .map(|home| home.join(\".ssh\").join(\"config\")),\n        system_config: None,\n        multiplexing: false,\n    }\n}\n\npub(crate) fn create_remote_ssh_config_dir(_control_socket_name: &str) -> std::io::Result<PathBuf> {\n    for attempt in 0..100 {\n        let dir = std::env::temp_dir().join(format!(\"herdr-ssh-{}-{attempt}\", std::process::id()));\n        match create_remote_private_dir(&dir) {\n            Ok(()) => return Ok(dir),\n            Err(err) if err.kind() == std::io::ErrorKind::AlreadyExists => continue,\n            Err(err) => return Err(err),\n        }\n    }\n    Err(std::io::Error::new(\n        std::io::ErrorKind::AlreadyExists,\n        \"failed to create private herdr ssh config directory\",\n    ))\n}\n\npub(crate) fn create_remote_ssh_config_file(\n    path: &std::path::Path,\n) -> std::io::Result<std::fs::File> {\n    let mut options = std::fs::OpenOptions::new();\n    options.write(true).create_new(true);\n    #[cfg(unix)]\n    {\n        use std::os::unix::fs::OpenOptionsExt;\n        options.mode(0o600);\n    }\n    options.open(path)\n}\n","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/herdrdev/herdr/blob/f457cff4f2648eee85d176f8a41861241d4e8428/src/platform/fallback.rs#L17-L53","documentation":"On fallback platforms, Herdr creates a private directory (~/.ssh-like, mode 700) for remote SSH control sockets and config. When every candidate private directory fails to create for a non-AlreadyExists reason and all paths are exhausted, this AlreadyExists error is returned as a terminal marker meaning 'no usable private directory could be established'.","triggerScenarios":"Calling create_remote_ssh_config_dir on a fallback platform when all candidate directories fail creation (permission denied on the parent, read-only home) or none of the attempted creations succeed. The AlreadyExists kind is a sentinel: candidates whose directory already exists are skipped, and reaching the end without success yields this error.","commonSituations":"Home directory permissions lock down creation of the private dir; HOME unset or pointing somewhere unwritable; sandboxed/containerized runs with a read-only home; tests that exhaust candidate paths deliberately.","solutions":["Check permissions on your home and SSH config directories; ensure the process can create mode-700 directories","Ensure HOME is set to a writable directory for the Herdr process","Pre-create the expected private herdr ssh directory with mode 700 so creation succeeds immediately","If running in a sandbox/container, mount or redirect HOME to writable storage"],"exampleFix":"// before: $HOME is read-only, creation fails\n// after: pre-create with correct perms\nmkdir -p ~/.local/share/herdr/ssh && chmod 700 ~/.local/share/herdr/ssh","handlingStrategy":"fallback","validationCode":"let dir = std::env::home_dir().unwrap_or_default().join(\".ssh\");\nif !dir.is_dir() && std::fs::create_dir_all(&dir).is_err() {\n    // surface a permissions problem before calling create_remote_ssh_config_dir\n}","typeGuard":null,"tryCatchPattern":"Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists && e.to_string().contains(\"private herdr ssh config\") => {\n    // treat as 'no usable private dir': prompt user or use a temp dir fallback\n}","preventionTips":["Ensure HOME is set and writable for the Herdr process","Pre-create the private directory with mode 700 during install","Log the underlying create_remote_private_dir errors, since the terminal marker hides them"],"tags":["ssh","filesystem","permissions","directory-creation","fallback-platform"],"backgroundTag":"directory-creation-permission-denied","analyzedSha":"f457cff4f2648eee85d176f8a41861241d4e8428","analyzedAt":"2026-08-28T15:41:09.197Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}