{"record":{"id":"c6e61576aca900a2","repo":"Hmbown/CodeWhale","slug":"source-is-not-a-directory-resume-fork-from","errorCode":null,"errorMessage":"{source} is not a directory: {}. Resume/fork from an existing workspace or pass an explicit `working_dir`/`cwd`","messagePattern":"(.+?) is not a directory: (.+?)\\. Resume/fork from an existing workspace or pass an explicit `working_dir`/`cwd`","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/shell.rs","lineNumber":142,"sourceCode":"fn validate_shell_working_dir(path: &Path, inherited_session_workspace: bool) -> Result<()> {\n    let metadata = std::fs::metadata(path).with_context(|| {\n        let source = if inherited_session_workspace {\n            \"saved session workspace\"\n        } else {\n            \"requested working directory\"\n        };\n        format!(\n            \"{source} is unavailable: {}. Restore or remap that directory, resume/fork the session from an existing workspace, or pass an explicit `working_dir`/`cwd` to exec_shell\",\n            path.display()\n        )\n    })?;\n    if !metadata.is_dir() {\n        let source = if inherited_session_workspace {\n            \"saved session workspace\"\n        } else {\n            \"requested working directory\"\n        };\n        return Err(anyhow!(\n            \"{source} is not a directory: {}. Resume/fork from an existing workspace or pass an explicit `working_dir`/`cwd`\",\n            path.display()\n        ));\n    }\n    Ok(())\n}\n\n/// Status of a shell process.\n#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]\npub enum ShellStatus {\n    Running,\n    Completed,\n    Failed,\n    Killed,\n    TimedOut,\n}\n\n/// Result from a shell command execution.","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/tools/shell.rs#L124-L160","documentation":"Before executing a shell command, the resolved working directory is stat'ed. A preceding check already handles the missing/unavailable path with a distinct message; this error fires when metadata exists but is not a directory (a regular file, socket, device, etc.). The message distinguishes whether the path came from a saved session workspace (inherited on resume/fork) or from an explicitly requested working directory, and names the offending path.","triggerScenarios":"Calling exec_shell with working_dir/cwd pointing at a file; or resuming/forking a session whose saved workspace path now exists but is not a directory (e.g. a file was created at that path).","commonSituations":"A symlink in the workspace path resolves to a file; the user passes a script path instead of its directory as cwd; on resume the old workspace was replaced by a file.","solutions":["Pass an explicit working_dir/cwd that is an existing directory.","If resuming/forking, resume from a session whose workspace directory actually exists, or remap the workspace.","Check the path with ls/stat to confirm it is a directory, and fix the entry (remove the blocking file or correct the symlink)."],"exampleFix":"# before\nexec_shell(\"cargo build\", working_dir=\"./run.sh\")\n\n# after\nexec_shell(\"cargo build\", working_dir=\"./\")","handlingStrategy":"validation","validationCode":"let dir: PathBuf = resolve_working_dir(requested, session)?;\nif !dir.is_dir() {\n    anyhow::bail!(\"working directory {} is not a directory\", dir.display());\n}\nexec_shell_with_dir(command, &dir)?;","typeGuard":null,"tryCatchPattern":"match exec_shell(cmd, Some(dir), None).await {\n    Ok(out) => out,\n    Err(e) if e.to_string().contains(\"is not a directory\") => {\n        let fallback = current_workspace_root();\n        exec_shell(cmd, Some(&fallback), None).await?\n    }\n    Err(e) => return Err(e),\n};","preventionTips":["Always pass working_dir as a directory that exists right now — verify with is_dir() before the call.","On resume/fork, validate the saved workspace still exists as a directory before running commands.","When resuming on another machine, remap the workspace or pass an explicit working_dir/cwd."],"tags":["shell","working-directory","filesystem","validation","session-resume"],"backgroundTag":"invalid-working-directory","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}