{"record":{"id":"f3f8106bc7164c30","repo":"astrid-runtime/astrid","slug":"workspace-state-path-must-be-a-real-directory-not","errorCode":null,"errorMessage":"workspace state path must be a real directory, not a redirect or file: {}","messagePattern":"workspace state path must be a real directory, not a redirect or file: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-core/src/workspace_security.rs","lineNumber":307,"sourceCode":"    }\n}\n\n#[derive(Debug, Clone, Copy, PartialEq, Eq)]\nenum DescendantKind {\n    Directory,\n    File,\n}\n\nfn verify_state_dir_path(project_root: &Path, state_dir: &Path) -> io::Result<()> {\n    crate::platform_fs::verify_no_redirects(project_root)?;\n    crate::platform_fs::verify_no_redirects(state_dir)?;\n    let metadata = match std::fs::symlink_metadata(state_dir) {\n        Ok(metadata) => metadata,\n        Err(error) if error.kind() == io::ErrorKind::NotFound => return Ok(()),\n        Err(error) => return Err(error),\n    };\n    if metadata.file_type().is_symlink() || !metadata.is_dir() {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidInput,\n            format!(\n                \"workspace state path must be a real directory, not a redirect or file: {}\",\n                state_dir.display()\n            ),\n        ));\n    }\n\n    let canonical = std::fs::canonicalize(state_dir)?;\n    if canonical != state_dir || canonical.parent() != Some(project_root) {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidInput,\n            format!(\n                \"workspace state directory escapes or redirects outside its selected path: {}\",\n                state_dir.display()\n            ),\n        ));\n    }","sourceCodeStart":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-core/src/workspace_security.rs#L289-L325","documentation":"This error is thrown when the workspace state directory path exists on disk but is either a symlink or a regular file instead of a real directory. The library requires state to live in a plain, physical directory so downstream canonicalization checks can guarantee it cannot be redirected.","triggerScenarios":"Calling `resolve` (which invokes `verify_state_dir_path`) when `state_dir` exists but `symlink_metadata` reports `is_symlink()` true or `is_dir()` false.","commonSituations":"Users symlink their state directory to another disk or dotfiles repo; a file was accidentally created at the state path by a misbehaving tool; a previous cleanup left a placeholder file.","solutions":["Remove the symlink or file at the state path and let the library create a real directory (e.g. `rm state_path && mkdir state_path`).","If you intended redirection, move the data into the real path instead of symlinking.","Re-run resolution after ensuring the path is a plain directory."],"exampleFix":"# before\nln -s /mnt/data/.astrid-state .astrid-state\n# after\nmkdir .astrid-state && rsync -a /mnt/data/.astrid-state/ .astrid-state/","handlingStrategy":"validation","validationCode":"use std::fs;\nfn state_dir_ok(p: &std::path::Path) -> bool {\n    match fs::symlink_metadata(p) {\n        Ok(m) => !m.file_type().is_symlink() && m.is_dir(),\n        Err(_) => true, // NotFound lets the library create it\n    }\n}","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 resolve(...) {\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidInput => {\n        std::fs::remove_file(state_dir).ok();\n        std::fs::create_dir_all(state_dir)?;\n        resolve(...)\n    }\n    other => other,\n}","preventionTips":["Never symlink workspace state directories; use bind mounts or real copies instead.","Check `ls -la` for symlinks in project config paths before running resolution.","Exclude state paths from dotfiles managers that replace files with symlinks."],"tags":["filesystem","symlink","validation"],"backgroundTag":"incompatible-source-type","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}