{"record":{"id":"f3498922c794bcec","repo":"gitbutlerapp/gitbutler","slug":"project-path-not-found","errorCode":null,"errorMessage":"project path not found","messagePattern":"project path not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/gitbutler-project/src/project.rs","lineNumber":319,"sourceCode":"\nimpl AddProjectOutcome {\n    /// This is for tests only.\n    ///\n    /// Unwraps the `Project` if the project was actually added.\n    /// Panics if it was not.\n    pub fn unwrap_project(self) -> Project {\n        match self {\n            AddProjectOutcome::Added(p) => p,\n            _ => panic!(\"called `AddProjectOutcome::unwrap_project()` on a non-project outcome\"),\n        }\n    }\n\n    /// Try to get the `Project`, returning an error if it was not added.\n    pub fn try_project(self) -> anyhow::Result<Project> {\n        match self {\n            AddProjectOutcome::Added(p) => Ok(p),\n            AddProjectOutcome::AlreadyExists(_) => Err(anyhow::anyhow!(\"project already exists\")),\n            AddProjectOutcome::PathNotFound => Err(anyhow::anyhow!(\"project path not found\")),\n            AddProjectOutcome::NotADirectory => {\n                Err(anyhow::anyhow!(\"project path is not a directory\"))\n            }\n            AddProjectOutcome::BareRepository => {\n                Err(anyhow::anyhow!(\"bare repositories are not supported\"))\n            }\n            AddProjectOutcome::NonMainWorktree => {\n                Err(anyhow::anyhow!(\"non-main worktrees are not supported\"))\n            }\n            AddProjectOutcome::NoWorkdir => Err(anyhow::anyhow!(\"no workdir found for repository\")),\n            AddProjectOutcome::NoDotGitDirectory => {\n                Err(anyhow::anyhow!(\"no .git directory found in repository\"))\n            }\n            AddProjectOutcome::ReftableRefFormatUnsupported => Err(anyhow::anyhow!(\n                \"unsupported repository reference format: reftable\"\n            )),\n            AddProjectOutcome::NotAGitRepository(msg) => {\n                Err(anyhow::anyhow!(\"not a git repository: {msg}\"))","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/gitbutler-project/src/project.rs#L301-L337","documentation":"AddProjectOutcome::PathNotFound mapped through try_project: add_project was called with a path that does not exist on disk. The path existence check runs before any git probing, so this is purely a filesystem precondition failure.","triggerScenarios":"add_project(path) where path was typo'd, relative and resolved against the wrong CWD, or deleted between user selection and the call; paths from stale config/sync on another machine; trailing whitespace or quotes in the path string.","commonSituations":"Paste-a-path flows in CLI/UI with typos; projects listed from another machine's settings; scripted setup referencing a checkout step that failed earlier so the directory was never created.","solutions":["Check the path exists before calling add_project: std::path::Path::exists","Normalize and canonicalize (std::fs::canonicalize) the path to eliminate relative-CWD and symlink surprises","Fix the upstream step that was supposed to create/clone the directory, then retry","In UI flows, use a native directory picker that only returns existing paths"],"exampleFix":"// before\nlet outcome = add_project(Path::new(&input), ...).try_project()?;\n\n// after: validate before adding\nlet path = std::fs::canonicalize(&input)\n    .with_context(|| format!(\"path does not exist: {input}\"))?;\nlet project = add_project(&path, ...).try_project()?;","handlingStrategy":"validation","validationCode":"let path = std::fs::canonicalize(&input)\n    .map_err(|_| anyhow!(\"path does not exist: {input}\"))?;\nlet project = add_project(&path, ...).try_project()?;","typeGuard":"fn existing_dir(p: impl AsRef<Path>) -> Option<std::path::PathBuf> {\n    std::fs::canonicalize(p).ok().filter(|p| p.is_dir())\n}","tryCatchPattern":"match add_project(Path::new(&input), ...) {\n    AddProjectOutcome::PathNotFound => {\n        // prompt the user with a directory picker instead of erroring out\n        pick_directory_and_retry()\n    }\n    outcome => outcome.try_project(),\n}","preventionTips":["canonicalize user-supplied paths before use to catch typos, relative-CWD issues, and missing paths early","Use native directory pickers that can only return existing folders","In automation, assert the clone/checkout step succeeded before adding its output directory"],"tags":["gitbutler","project","filesystem","validation"],"backgroundTag":"path-not-found","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-23T16:17:53.355Z"}