{"record":{"id":"3656a8845281fa6a","repo":"astrid-runtime/astrid","slug":"astrid-home-without-a-layout-sentinel-is-redirecte","errorCode":null,"errorMessage":"Astrid home without a layout sentinel is redirected or not a directory: {}","messagePattern":"Astrid home without a layout sentinel is redirected or not a directory: (.+?)","errorType":"validation","errorClass":"std::io::Error::InvalidData","httpStatus":null,"severity":"error","filePath":"crates/astrid-core/src/dirs.rs","lineNumber":352,"sourceCode":"    /// # Errors\n    ///\n    /// Returns an error if directory creation or permission setting fails.\n    pub fn ensure(&self) -> io::Result<()> {\n        self.validate_run_dir()?;\n        let existing_layout = self.layout_version()?;\n        if let Some(version) = existing_layout.as_deref()\n            && version != LEGACY_LAYOUT_VERSION\n            && version != LAYOUT_VERSION\n        {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidData,\n                format!(\"unsupported Astrid home layout version {version:?}\"),\n            ));\n        }\n        if existing_layout.is_none() {\n            match std::fs::symlink_metadata(self.root()) {\n                Ok(metadata) if metadata.file_type().is_symlink() || !metadata.is_dir() => {\n                    return Err(io::Error::new(\n                        io::ErrorKind::InvalidData,\n                        format!(\n                            \"Astrid home without a layout sentinel is redirected or not a directory: {}\",\n                            self.root().display()\n                        ),\n                    ));\n                },\n                Ok(_) => {},\n                Err(error) if error.kind() == io::ErrorKind::NotFound => {},\n                Err(error) => return Err(error),\n            }\n        }\n        let mut dirs = Vec::<PathBuf>::new();\n        if existing_layout.as_deref() == Some(LEGACY_LAYOUT_VERSION) {\n            dirs.extend([\n                self.etc_dir(),\n                self.hooks_dir(),\n                self.var_dir(),","sourceCodeStart":334,"sourceCodeEnd":370,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-core/src/dirs.rs#L334-L370","documentation":"Thrown by AstridDirs::ensure when the home root has no layout sentinel, and the root itself is either a symlink or not a directory. This guards against redirected or malformed roots being silently initialized as an Astrid home.","triggerScenarios":"Calling ensure on a path where the root is a symlink (e.g. redirecting the home elsewhere) or a regular file/socket, with no layout sentinel present.","commonSituations":"Users symlinking their Astrid home to another volume, a stale file occupying the expected home path, or a partially deleted home directory.","solutions":["Replace the symlink/file at the home path with a real directory and re-run ensure","Remove the stale non-directory entry and re-initialize the home","If redirection is intended, point ASTRID_HOME directly at the target directory"],"exampleFix":"// before: root is a symlink\nln -s /mnt/volume/.astrid ~/.astrid\n// after: use the target path directly\nexport ASTRID_HOME=/mnt/volume/.astrid","handlingStrategy":"validation","validationCode":"let md = std::fs::symlink_metadata(&home_path)?;\nassert!(md.is_dir() && !md.file_type().is_symlink(), \"home must be a real directory\");","typeGuard":"fn is_real_dir(p: &std::path::Path) -> bool {\n    std::fs::symlink_metadata(p).map(|m| m.is_dir() && !m.file_type().is_symlink()).unwrap_or(false)\n}","tryCatchPattern":"match dirs.ensure() {\n    Err(e) if e.to_string().contains(\"redirected or not a directory\") => {\n        eprintln!(\"Home path is a symlink or non-directory; fix the path\");\n    },\n    other => other?,\n}","preventionTips":["Don't symlink the Astrid home; point ASTRID_HOME at the target instead","Check for leftover files at the home path after uninstalls","Run symlink_metadata checks in deployment scripts"],"tags":["filesystem","symlink","layout"],"backgroundTag":"invalid-state-transition","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}