{"record":{"id":"ed05ab654c822b11","repo":"gitbutlerapp/gitbutler","slug":"not-a-git-repository-msg","errorCode":null,"errorMessage":"not a git repository: {msg}","messagePattern":"not a git repository: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/gitbutler-project/src/project.rs","lineNumber":337,"sourceCode":"            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}\"))\n            }\n        }\n    }\n}\n","sourceCodeStart":319,"sourceCodeEnd":342,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/gitbutler-project/src/project.rs#L319-L342","documentation":"AddProjectOutcome::NotAGitRepository(msg) mapped through try_project: the path contains something git-like or the discovery failed, and gix returned a specific reason carried in {msg} (e.g. 'not a git repository' style discovery errors). This is the generic fallback when the failure is not one of the precise cases (path missing, not a directory, bare, worktree, no .git, reftable).","triggerScenarios":"add_project on a directory where git discovery runs but errors: corrupted .git contents, unreadable config files, invalid repository format version (extensions enabled by a newer git, e.g. objectformat=sha256 in unsupported builds), permission errors reading .git internals.","commonSituations":"Repos created by much newer git versions with incompatible extensions (sha256 object format, sparse-index-only features); .git partially copied or synced with missing files; OS-level permission problems on .git contents.","solutions":["Read the embedded {msg} — it carries gix's actual reason for refusing the repository","Check for newer-git extensions: `git config --list --show-origin | grep -i extension` and disable unsupported ones (e.g. extensions.objectformat)","Verify with the CLI in the same directory: `git -C <path> status` — if the CLI also fails, fix the repository first","For sha256 repos, use a standard sha1 clone until the app supports the object format"],"exampleFix":"// before\nlet project = add_project(&path, ...).try_project()?; // 'not a git repository: <msg>'\n\n// after: surface the specific reason to guide the fix\nmatch add_project(&path, ...) {\n    AddProjectOutcome::NotAGitRepository(msg) => {\n        return Err(anyhow!(\"cannot add {path:?}: {msg} — check git extensions and .git integrity\"));\n    }\n    outcome => outcome.try_project()?,\n}","handlingStrategy":"validation","validationCode":"// cheapest reliable probe: ask git itself if the directory opens as a repo\nlet probe = std::process::Command::new(\"git\")\n    .args([\"-C\", &path.to_string_lossy(), \"rev-parse\", \"--git-dir\"])\n    .output()?;\nif !probe.status.success() {\n    anyhow::bail!(\"{} is not a usable git repository: {}\", path.display(), String::from_utf8_lossy(&probe.stderr));\n}\n// also screen incompatible extensions (e.g. sha256 object format)\nlet ext = std::process::Command::new(\"git\")\n    .args([\"-C\", &path.to_string_lossy(), \"config\", \"extensions.objectformat\"])\n    .output()?;\nif ext.stdout.trim() == b\"sha256\" {\n    anyhow::bail!(\"sha256 object format is not supported — use a sha1 clone\");\n}","typeGuard":"fn is_openable_git_repo(path: &Path) -> bool {\n    std::process::Command::new(\"git\")\n        .args([\"-C\", &path.to_string_lossy(), \"rev-parse\", \"--git-dir\"])\n        .output()\n        .map(|o| o.status.success())\n        .unwrap_or(false)\n}","tryCatchPattern":"match add_project(&path, ...) {\n    AddProjectOutcome::NotAGitRepository(msg) => {\n        // msg carries gix's specific reason: show it, suggest fixing extensions/.git\n        show_actionable_error(&msg)\n    }\n    outcome => outcome.try_project(),\n}","preventionTips":["Probe candidate directories with `git rev-parse --git-dir` before onboarding","Watch for newer-git extensions (objectformat, refstorage) in repo config and reject with guidance","Never partially copy or sync .git directories — incomplete repos land in this catch-all case"],"tags":["gitbutler","project","git","compatibility","validation"],"backgroundTag":"not-a-git-repository","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-23T16:17:53.355Z"}