{"record":{"id":"d46cb26537c5fe6b","repo":"xai-org/grok-build","slug":"local-workspace-cwd-must-exist-and-be-canonicaliza","errorCode":null,"errorMessage":"local workspace cwd must exist and be canonicalizable: {}: {e}","messagePattern":"local workspace cwd must exist and be canonicalizable: (.+?): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-pager/src/app/session_startup.rs","lineNumber":508,"sourceCode":"///\n/// Returns the canonical directory so callers stamp and persist what was actually checked (symlinks and `..` must not diverge from validation).\n#[cfg(feature = \"local-workspace\")]\npub fn validate_local_workspace_cwd(path: &std::path::Path) -> anyhow::Result<std::path::PathBuf> {\n    let abs = if path.is_absolute() {\n        path.to_path_buf()\n    } else {\n        std::env::current_dir()\n            .unwrap_or_else(|_| std::path::PathBuf::from(\".\"))\n            .join(path)\n    };\n    let canon = abs.canonicalize().map_err(|e| {\n        anyhow::anyhow!(\n            \"local workspace cwd must exist and be canonicalizable: {}: {e}\",\n            abs.display()\n        )\n    })?;\n    if !canon.is_dir() {\n        anyhow::bail!(\n            \"local workspace cwd must be an existing directory: {}\",\n            canon.display()\n        );\n    }\n    if env_truthy(GROK_CHAT_LOCAL_WORKSPACE_ALLOW_HOME_ENV) {\n        return Ok(canon);\n    }\n    if canon == std::path::Path::new(\"/\") {\n        anyhow::bail!(\"{LOCAL_WORKSPACE_HOME_DENIED}\");\n    }\n    if let Some(home_path) = xai_dirs::home_dir() {\n        let home_canon = home_path.canonicalize().unwrap_or(home_path);\n        if canon == home_canon {\n            anyhow::bail!(\"{LOCAL_WORKSPACE_HOME_DENIED}\");\n        }\n    }\n    Ok(canon)\n}","sourceCodeStart":490,"sourceCodeEnd":526,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-pager/src/app/session_startup.rs#L490-L526","documentation":"`validate_local_workspace_cwd` must canonicalize the requested workspace directory. If `canonicalize()` fails (path does not exist, is a broken symlink, or a permission error occurs), it wraps the io::Error with `local workspace cwd must exist and be canonicalizable: <path>: <e>` (session_startup.rs:503).","triggerScenarios":"Passing a `--local-workspace` cwd or GROK_CHAT_LOCAL_WORKSPACE_CWD pointing to a non-existent path; a dangling symlink; a path under a directory the user cannot traverse; cwd deleted after shell start.","commonSituations":"Typo'd directory names; workspaces on unmounted network drives; running inside a container where the host path does not exist.","solutions":["Create the directory (`mkdir -p <path>`) or correct the path/typo","Fix or remove broken symlinks","Verify mount/permissions for the path (ls -ld)","Set GROK_CHAT_LOCAL_WORKSPACE_CWD to an existing absolute path"],"exampleFix":"// before\nexport GROK_CHAT_LOCAL_WORKSPACE_CWD=~/projects/missing-dir\n// after\nmkdir -p ~/projects/my-workspace\nexport GROK_CHAT_LOCAL_WORKSPACE_CWD=~/projects/my-workspace","handlingStrategy":"validation","validationCode":"fn precheck_cwd(p: &std::path::Path) -> Result<(), String> {\n    let canon = p.canonicalize().map_err(|e| format!(\"cwd unusable: {p:?}: {e}\"))?;\n    if !canon.is_dir() { return Err(format!(\"not a directory: {}\", canon.display())); }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match validate_local_workspace_cwd(&cwd) {\n    Err(e) if e.to_string().contains(\"canonicalizable\") => {\n        eprintln!(\"create the directory or fix the path before retrying: {e}\")\n    }\n    other => other?,\n}","preventionTips":["mkdir -p the workspace before launching","Use absolute paths from `realpath` to avoid broken symlinks","Verify mounts (network drives, containers) exist before runs","Re-validate cwd if the shell has been alive across filesystem changes"],"tags":["filesystem","path-validation","local-workspace"],"backgroundTag":"path-not-found","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}