astrid-runtime/astrid · error

failed to resolve workspace root {}: {error}

Error message

failed to resolve workspace root {}: {error}

What it means

WorkspaceSelection::resolve canonicalizes the supplied project_root to obtain the true absolute workspace root, and wraps any std::fs::canonicalize failure (not-found, permission denied, symlink loop, I/O error) in an io::Error preserving the original kind while adding context: the unresolved path and the underlying OS error. The library cannot establish a trusted workspace root without a canonical path.

Source

Thrown at crates/astrid-core/src/workspace_security.rs:26

use super::WorkspaceLayout;

/// A checked project workspace selection.
///
/// The project root is canonical and the selected state directory is either
/// absent or a real directory directly beneath that root. Symlinks, junctions,
/// and other redirects are rejected by requiring an existing directory to
/// canonicalize to the exact direct-child path selected here.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WorkspaceSelection {
    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()
                ),
            ));
        }

View on GitHub (pinned to affd8760f4)

Solutions

  1. Create the project root directory if it does not exist (std::fs::create_dir_all) before resolving the workspace.
  2. Fix the configured project root path (typo, wrong cwd, relative path resolved from an unexpected working directory).
  3. Repair or remove broken symlinks along the path.
  4. Check permissions on every path component so the process can traverse to the root.
  5. Investigate the wrapped OS error in the message (e.g. ENOENT vs EACCES vs ELOOP) to target the exact cause.

Example fix

// before
let sel = WorkspaceSelection::resolve(Path::new("/opt/missing-project"), layout)?;
// after
let root = Path::new("/opt/my-project");
std::fs::create_dir_all(root)?;
let sel = WorkspaceSelection::resolve(root, layout)?;
Defensive patterns

Strategy: validation

Validate before calling

fn root_ready(p: &Path) -> std::io::Result<()> {
    let meta = std::fs::metadata(p).map_err(|e| e)?;
    if !meta.is_dir() { return Err(io::Error::new(io::ErrorKind::InvalidInput, "not a dir")); }
    Ok(())
}

Try / catch

match WorkspaceSelection::resolve(root, layout) {
    Err(e) => { log::error!("cannot resolve workspace root: {e}"); return Err(e); }
    Ok(sel) => sel,
}

Prevention

When it happens

Trigger: Calling WorkspaceSelection::resolve (directly or via ensure_state_dir / resolve_directory / resolve_file / verify) with a project_root that does not exist, is unreadable due to permissions, sits behind a broken symlink, or contains a symlink loop.

Common situations: Typo in the configured project root; running before project initialization created the directory; the workspace was deleted or moved while the process held a stale path; NFS/network mounts returning EIO; restrictive file permissions after a container user switch.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/9a2fc6ba117fd672. Report an issue: GitHub.