{"record":{"id":"6e727a50e86f1fde","repo":"gitbutlerapp/gitbutler","slug":"projectmissing","errorCode":"ProjectMissing","errorMessage":"Could not open repository at '{}'{suffix}","messagePattern":"Could not open repository at '(.+?)'(.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/gitbutler-project/src/controller.rs","lineNumber":299,"sourceCode":"    /// Like [`Self::get()`], but will assure the project still exists and is valid by\n    /// opening a git repository. This should only be done for critical points in time.\n    pub(crate) fn get_validated(&self, id: ProjectHandleOrLegacyProjectId) -> Result<Project> {\n        self.get_inner(id, true)\n    }\n\n    fn get_inner(&self, id: ProjectHandleOrLegacyProjectId, validate: bool) -> Result<Project> {\n        let mut project = self.projects_storage.get(id)?;\n        // BACKWARD-COMPATIBLE MIGRATION\n        project.migrate()?;\n        if validate {\n            let repo = project.open_isolated_repo();\n            if repo.is_err() {\n                let suffix = if !project.worktree_dir.exists() {\n                    \" as it does not exist\"\n                } else {\n                    \"\"\n                };\n                return Err(anyhow!(\n                    \"Could not open repository at '{}'{suffix}\",\n                    project.worktree_dir.display()\n                )\n                .context(Code::ProjectMissing));\n            }\n        }\n\n        match project.gb_dir() {\n            Ok(gb_dir) => {\n                if !gb_dir.exists()\n                    && let Err(error) = std::fs::create_dir_all(&gb_dir)\n                {\n                    tracing::error!(project_id = %project.id, ?error, \"failed to create \\\"{}\\\" on project get\", gb_dir.display());\n                }\n            }\n            Err(error) => {\n                tracing::error!(project_id = %project.id, ?error, \"failed to resolve storage directory on project get\");\n            }","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/gitbutler-project/src/controller.rs#L281-L317","documentation":"ProjectController::get_inner validates that the project's worktree directory still hosts an openable git repository before returning the Project. If repo opening fails, the error includes the worktree path plus a suffix explaining that the directory does not exist when that is the case, and is wrapped with the ProjectMissing error code. Callers get/get_validated surface this when a registered project has disappeared from disk.","triggerScenarios":"Calling get or get_validated for a project whose worktree_dir was deleted/moved, is on an unmounted drive, or whose `.git` is corrupted so git2 cannot open the repository.","commonSituations":"User deleted or renamed the project folder while GitButler still lists it; external drive or network mount offline; repo moved to a different path; antivirus or sync tools interfering with the .git directory.","solutions":["Recreate or restore the directory at the recorded worktree path (restore from backup, remount the drive, undo the rename).","Remove the project from GitButler's project list and re-add it at its new location.","Check the path exists and is a valid repo before loading: `ls <path>/.git` and `git -C <path> status`.","If .git is corrupted, re-clone and re-add the project."],"exampleFix":"// before: loading a stale project blindly\nlet project = controller.get(project_id)?;\n// after: validate path first\nif !std::path::Path::new(&worktree_dir).join(\".git\").exists() {\n    // re-add project at new location or remove it\n}\nlet project = controller.get_validated(project_id)?;","handlingStrategy":"validation","validationCode":"fn project_path_valid(worktree_dir: &std::path::Path) -> bool {\n    worktree_dir.exists() && worktree_dir.join(\".git\").exists()\n}","typeGuard":null,"tryCatchPattern":"match controller.get_validated(project_id) {\n    Err(e) if e.to_string().starts_with(\"Could not open repository at\") => {\n        // prompt user to relocate or remove the project\n        handle_missing_project(project_id)\n    }\n    other => other,\n}","preventionTips":["Don't delete or rename project folders while GitButler has them registered.","Keep repos on always-mounted local disks when possible.","Remove projects from GitButler before deleting their directories.","Periodically prune stale project entries."],"tags":["git","project","missing-directory","worktree"],"backgroundTag":"directory-not-found","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}