xai-org/grok-build · error · anyhow::Error
not a git repository: {}
Error message
not a git repository: {} What it means
find_git_root_from_path() walks up from the given path via discover_git_root(); when the discovery reports NotARepo (no .git found up to the filesystem root), it bails naming the offending path. Callers use it to locate the repo root before worktree creation, resume, cleanup, or subdir offset computation.
Source
Thrown at crates/codegen/xai-grok-workspace/src/session/git.rs:419
let head_commit = head_ref
.as_ref()
.and_then(|h| h.target())
.map(|oid| oid.to_string());
let head_branch = head_ref
.as_ref()
.and_then(|h| h.shorthand().filter(|s| *s != "HEAD").map(str::to_owned));
PersistedGitMetadata {
git_root_dir: Some(git_root.to_string_lossy().to_string()),
git_remotes: remotes.into_iter().collect(),
head_commit,
head_branch,
}
}
pub fn find_git_root_from_path(path: &Path) -> Result<PathBuf> {
match discover_git_root(path) {
GitDiscoveryResult::Found(root) => Ok(root),
GitDiscoveryResult::NotARepo => {
anyhow::bail!("not a git repository: {}", path.display())
}
GitDiscoveryResult::DiscoveryFailed(e) => Err(e),
}
}
/// Find the main repo root (not the worktree working directory).
/// For regular repos this is the same as find_git_root_from_path.
/// For worktrees, this returns the parent repo's root.
/// Use this for worktree management operations (create/remove/apply).
pub fn find_main_repo_root_from_path(path: &Path) -> Result<PathBuf> {
let repo = Repository::discover(path)?;
repo.commondir()
.parent()
.map(|p| p.to_path_buf())
.ok_or_else(|| anyhow::anyhow!("Invalid git repository: {}", path.display()))
}
pub fn change_type_from_git2_delta(delta: git2::Delta) -> ChangeType {
match delta {
git2::Delta::Added => ChangeType::Create,View on GitHub (pinned to bc7f02eddd)
Solutions
- Run `git -C <path> rev-parse --show-toplevel` to confirm the path is inside a repo
- Pass the actual repo (or a path under it) instead of a scratch directory
- Restore/re-clone the repository if .git was deleted
- Fix the configured workspace/session path that points outside the repo
Example fix
// before
let root = find_git_root_from_path(Path::new("/tmp/session-123"))?;
// after
let root = find_git_root_from_path(Path::new("/home/dev/project/src/..."))?; // inside the repo Defensive patterns
Strategy: validation
Validate before calling
fn ensure_inside_repo(p: &Path) -> anyhow::Result<()> {
let out = std::process::Command::new("git").arg("-C").arg(p).args(["rev-parse","--show-toplevel"]).output()?;
if !out.status.success() { anyhow::bail!("{} is not inside a git repository", p.display()); }
Ok(())
} Type guard
fn is_git_repo(p: &Path) -> bool { p.ancestors().any(|a| a.join(".git").exists()) } Try / catch
match find_git_root_from_path(&path) {
Ok(root) => use_root(root),
Err(e) if e.to_string().starts_with("not a git repository") => {
// prompt user to point at the repo or re-clone
}
Err(e) => return Err(e),
} Prevention
- Store/resolve workspace paths from the repo root, never scratch dirs
- Check for .git (or use git rev-parse) at startup before any session operations
- Re-validate recorded session paths — repos can be moved or deleted
- Canonicalize paths (dunce::canonicalize) before discovery
When it happens
Trigger: Calling create_worktree_for_resume, cleanup_worktree_on_failure, resume_local_session_in_worktree, or compute_subdir_offset with a path outside any git repository (e.g. /tmp, a home directory, or a session directory recorded before the repo was moved/deleted).
Common situations: Pointing a resume at a workspace copy without .git; repo deleted or .git removed; passing an absolute path on a different mount that has no repo ancestor; typos in the configured workspace path.
Related errors
- not a git repository: {}
- unsupported checkout target (need a full commit oid or a sim
- refusing unsafe fetch refspec
- destination has no filename: {}
- bare git repository: {}
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/ed8c782fda7aa23b.
Report an issue: GitHub.