astrid-runtime/astrid · error
workspace root is not a directory: {}
Error message
workspace root is not a directory: {} What it means
After canonicalizing the project root and verifying it does not redirect through symlinks, WorkspaceSelection::resolve stats the path and rejects it with InvalidInput if it is not a directory. A workspace root must be an actual directory; pointing it at a regular file (or special file) is a configuration error.
Source
Thrown at crates/astrid-core/src/workspace_security.rs:36
project_root: PathBuf,
state_dir: PathBuf,
layout: WorkspaceLayout,
}
impl WorkspaceSelection {
pub(super) fn resolve(project_root: &Path, layout: WorkspaceLayout) -> io::Result<Self> {
let project_root = std::fs::canonicalize(project_root).map_err(|error| {
io::Error::new(
error.kind(),
format!(
"failed to resolve workspace root {}: {error}",
project_root.display()
),
)
})?;
crate::platform_fs::verify_no_redirects(&project_root)?;
if !std::fs::metadata(&project_root)?.is_dir() {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!(
"workspace root is not a directory: {}",
project_root.display()
),
));
}
let state_dir = project_root.join(layout.state_dir_name());
verify_state_dir_path(&project_root, &state_dir)?;
Ok(Self {
project_root,
state_dir,
layout,
})
}
/// Canonical project root used by every workspace filesystem consumer.View on GitHub (pinned to affd8760f4)
Solutions
- Point project_root at the workspace directory, not a file inside it.
- If the directory was replaced by a file, restore it (recreate the directory and move contents back).
- Add an is_dir() precheck on the configured path before constructing the workspace selection.
- Fix mounts/symlinks that shadow the intended directory.
Example fix
// before
let sel = WorkspaceSelection::resolve(Path::new("/srv/app/Cargo.toml"), layout)?;
// after
let sel = WorkspaceSelection::resolve(Path::new("/srv/app"), layout)?; Defensive patterns
Strategy: validation
Validate before calling
let meta = std::fs::metadata(&root)?;
assert!(meta.is_dir(), "project root must be a directory: {}", root.display()); Prevention
- Validate configured roots point at directories at startup
- Distinguish file-path vs directory-path config fields clearly
- Prefer canonical paths from a single source of truth in configuration
When it happens
Trigger: Calling WorkspaceSelection::resolve with a project_root that canonicalizes to a regular file, FIFO, socket, or device node instead of a directory.
Common situations: Config pointing at a file like project.toml instead of the project directory; a mount or symlink swapping the directory for a file; automation passing the wrong variable (file path vs directory path).
Related errors
- private host-file validation is unavailable on this target
- failed to resolve workspace root {}: {error}
- capsule source is neither a directory nor a regular file: {}
- legacy env/secret path is not a regular directory: {}
- MCP attach workspace must be absolute: {value}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/db6a7e8c2526dffb.
Report an issue: GitHub.