astrid-runtime/astrid · error
workspace state path must be a real directory, not a redirec
Error message
workspace state path must be a real directory, not a redirect or file: {} What it means
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.
Source
Thrown at crates/astrid-core/src/workspace_security.rs:307
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum DescendantKind {
Directory,
File,
}
fn verify_state_dir_path(project_root: &Path, state_dir: &Path) -> io::Result<()> {
crate::platform_fs::verify_no_redirects(project_root)?;
crate::platform_fs::verify_no_redirects(state_dir)?;
let metadata = match std::fs::symlink_metadata(state_dir) {
Ok(metadata) => metadata,
Err(error) if error.kind() == io::ErrorKind::NotFound => return Ok(()),
Err(error) => return Err(error),
};
if metadata.file_type().is_symlink() || !metadata.is_dir() {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!(
"workspace state path must be a real directory, not a redirect or file: {}",
state_dir.display()
),
));
}
let canonical = std::fs::canonicalize(state_dir)?;
if canonical != state_dir || canonical.parent() != Some(project_root) {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!(
"workspace state directory escapes or redirects outside its selected path: {}",
state_dir.display()
),
));
}View on GitHub (pinned to affd8760f4)
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.
Example fix
# before ln -s /mnt/data/.astrid-state .astrid-state # after mkdir .astrid-state && rsync -a /mnt/data/.astrid-state/ .astrid-state/
Defensive patterns
Strategy: validation
Validate before calling
use std::fs;
fn state_dir_ok(p: &std::path::Path) -> bool {
match fs::symlink_metadata(p) {
Ok(m) => !m.file_type().is_symlink() && m.is_dir(),
Err(_) => true, // NotFound lets the library create it
}
} Type guard
fn is_real_dir(p: &std::path::Path) -> bool {
std::fs::symlink_metadata(p).map(|m| m.is_dir() && !m.file_type().is_symlink()).unwrap_or(false)
} Try / catch
match resolve(...) {
Err(e) if e.kind() == std::io::ErrorKind::InvalidInput => {
std::fs::remove_file(state_dir).ok();
std::fs::create_dir_all(state_dir)?;
resolve(...)
}
other => other,
} Prevention
- 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.
When it happens
Trigger: Calling `resolve` (which invokes `verify_state_dir_path`) when `state_dir` exists but `symlink_metadata` reports `is_symlink()` true or `is_dir()` false.
Common situations: 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.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- legacy env/secret path is not a regular directory: {}
- workspace path must not contain redirects or unexpected file
- legacy principal-home root is not a directory: {}
- legacy principal-home entry is not a regular directory: {}
- legacy source is not a regular file: {}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/f3f8106bc7164c30.
Report an issue: GitHub.