{"record":{"id":"b4b778c712ac56be","repo":"gitbutlerapp/gitbutler","slug":"repoownership","errorCode":"RepoOwnership","errorMessage":"The git directory is considered unsafe as it's not owned by the current user. Use `git config --global --add safe.directory '{}'` to allow it","messagePattern":"The git directory is considered unsafe as it's not owned by the current user\\. Use `git config --global --add safe\\.directory '(.+?)'` to allow it","errorType":"exception","errorClass":"but_error::Code","httpStatus":null,"severity":"error","filePath":"crates/but-api/src/legacy/projects.rs","lineNumber":194,"sourceCode":"\n/// Prepare an already-known project for activation in the UI or server.\n///\n/// This repairs missing target metadata in freshly selected storage locations.\npub fn prepare_project_for_activation(ctx: &mut Context) -> Result<()> {\n    assure_repo_ownership(&*ctx.repo.get()?)?;\n    let _guard = ctx.exclusive_worktree_access();\n    gitbutler_branch_actions::base::bootstrap_default_target_if_missing(ctx)?;\n    Ok(())\n}\n\n// TODO(gix): remove this once there is no `git2` as `gix` provides safety by not trusting Git configuration instead.\nfn assure_repo_ownership(repo: &gix::Repository) -> Result<()> {\n    if repo.git_dir_trust() == gix::sec::Trust::Full {\n        return Ok(());\n    }\n\n    let path = repo.workdir().unwrap_or(repo.git_dir());\n    Err(anyhow!(\n        \"The git directory is considered unsafe as it's not owned by the current user. Use `git config --global --add safe.directory '{}'` to allow it\",\n        path.display()\n    )\n    .context(Code::RepoOwnership))\n}\n\n#[but_api]\n#[instrument(err(Debug))]\npub fn is_gerrit(ctx: &but_ctx::Context) -> Result<bool> {\n    let repo = ctx.repo.get()?;\n    Ok(\n        gitbutler_project::gerrit::is_used_by_default_remote(&repo).unwrap_or_else(|err| {\n            tracing::debug!(?err, \"Gerrit detection failed\");\n            false\n        }),\n    )\n}\n","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/2497b8007aa4a1922dae9a805b32ffe5b5037785/crates/but-api/src/legacy/projects.rs#L176-L212","documentation":"assure_repo_ownership() mirrors git's 'dubious ownership' protection using gix: if the repository's git dir is not fully trusted (owned by a user other than the current one), project operations abort with Code::RepoOwnership and the message includes the exact safe.directory command to run.","triggerScenarios":"Adding or opening a project whose .git directory is owned by another uid: cloned with sudo, created inside a container or volume mount, copied from another user, or living on a filesystem with unexpected ownership.","commonSituations":"Docker/VM shared-folder checkouts; repos set up by an admin; home directories copied between users; CI running as a different user than the checkout owner.","solutions":["Run the command from the message as the user running GitButler: git config --global --add safe.directory '<path>'","Alternatively fix the root cause: sudo chown -R $(id -u):$(id -g) <repo-path>","Reopen or re-add the project in GitButler"],"exampleFix":"# before: project fails to open with Code::RepoOwnership\n\n# after (as the user running GitButler)\ngit config --global --add safe.directory /home/user/projects/my-repo\n# or fix the root cause:\nsudo chown -R $(id -u):$(id -g) /home/user/projects/my-repo","handlingStrategy":"validation","validationCode":"fn repo_is_trusted(repo: &gix::Repository) -> bool {\n    repo.git_dir_trust() == gix::sec::Trust::Full\n}\n\n// before adding/opening the project:\nif !repo_is_trusted(&repo) {\n    // show safe.directory/chown guidance instead of failing later\n}","typeGuard":"use but_error::{AnyhowContextExt, Code};\n\nfn is_repo_ownership_error(err: &anyhow::Error) -> bool {\n    err.custom_context().is_some_and(|c| c.code == Code::RepoOwnership)\n}","tryCatchPattern":"match open_project(ctx, id) {\n    Err(err) if is_repo_ownership_error(&err) => {\n        // show the safe.directory command from the message and let the user fix ownership\n    }\n    other => other,\n}","preventionTips":["Clone repos as the user that runs GitButler","After restoring or copying repos, chown them to the working user","Check git_dir_trust before registering a project path"],"tags":["git","ownership","permissions","posix","gix","security"],"backgroundTag":"git-safe-directory","analyzedSha":"2497b8007aa4a1922dae9a805b32ffe5b5037785","analyzedAt":"2026-08-17T00:30:25.648Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}