{"record":{"id":"cefcca2e65b127cf","repo":"xai-org/grok-build","slug":"no-git-file-or-directory-found-at","errorCode":null,"errorMessage":"no .git file or directory found at {}","messagePattern":"no \\.git file or directory found at (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-fast-worktree/src/git/discovery.rs","lineNumber":39,"sourceCode":"            .ok_or_else(|| anyhow::anyhow!(\"invalid .git file format: {}\", content.trim()))?\n            .trim();\n\n        // git may write a RELATIVE pointer (worktrees added with a relative\n        // path). Resolve it against the worktree dir — otherwise downstream\n        // index lookups join it against the CWD and break (mirrors\n        // `read_worktree_gitdir` in api.rs).\n        let raw_path = Path::new(raw);\n        let resolved = if raw_path.is_relative() {\n            worktree_path.join(raw_path)\n        } else {\n            raw_path.to_path_buf()\n        };\n        Ok(dunce::canonicalize(&resolved).unwrap_or(resolved))\n    } else if git_path.is_dir() {\n        // Regular repository\n        Ok(git_path)\n    } else {\n        anyhow::bail!(\n            \"no .git file or directory found at {}\",\n            worktree_path.display()\n        )\n    }\n}\n\n/// Find the worktree root (working directory root) for a path.\n///\n/// This handles both regular repositories and worktrees correctly.\n/// For a regular repo at `/repo`, returns `/repo`.\n/// For a worktree at `/worktrees/wt1`, returns `/worktrees/wt1`.\n/// For a subdirectory `/repo/subdir`, returns `/repo`.\npub(crate) fn find_worktree_root(path: &Path) -> Result<PathBuf> {\n    let repo = gix::discover(path)\n        .with_context(|| format!(\"failed to discover git repo at {}\", path.display()))?;\n\n    // workdir() returns the working directory root for both repos and worktrees\n    let work_dir = repo","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-fast-worktree/src/git/discovery.rs#L21-L57","documentation":"find_worktree_git_dir resolves a worktree's git directory. If the path it checks contains neither a `.git` file (linked worktree) nor a `.git` directory (regular repo), it bails with this message naming the worktree path. The library throws it because without a git dir there is no index to copy or stats to update.","triggerScenarios":"Calling find_worktree_git_dir (directly, or via copy_git_index / update_index_stats) on a directory where `<path>/.git` does not exist — the directory isn't a git repo or worktree at all, or is an orphaned bare checkout whose .git was deleted/moved.","commonSituations":"Pointing the library at the worktree's checkout content directory instead of its root; a worktree whose .git file was deleted after `git worktree prune` or an rsync that skipped dotfiles; running cleanup on a directory that was already removed; typos in the worktree path.","solutions":["Verify the path is a worktree root containing .git: run `ls -a <path>/.git` and correct the path if it's missing.","If .git was pruned/lost, recreate the worktree with `git worktree add <path> <ref>` instead of repairing it.","If rsync/copy tooling dropped dotfiles, re-copy with dotfiles included (e.g. `rsync -a` without `--exclude=.git`).","Check for a stale registration: `git worktree list` and `git worktree prune` to clean entries pointing at non-existent checkouts."],"exampleFix":"// before: calling with a subdirectory of the checkout\nlet git_dir = find_worktree_git_dir(&Path::new(\"/srv/wt/main/src\"))?;\n// after: guard that the target actually has .git\nlet root = Path::new(\"/srv/wt/main\");\nif !root.join(\".git\").exists() {\n    anyhow::bail!(\"{} is not a git worktree root\", root.display());\n}\nlet git_dir = find_worktree_git_dir(root)?;","handlingStrategy":"validation","validationCode":"fn ensure_worktree_root(path: &std::path::Path) -> anyhow::Result<()> {\n    let git = path.join(\".git\");\n    if !git.exists() {\n        anyhow::bail!(\"{} is not a git repo/worktree (no .git)\", path.display());\n    }\n    Ok(())\n}","typeGuard":"fn has_git_dir(path: &std::path::Path) -> bool {\n    path.join(\".git\").is_dir() || path.join(\".git\").is_file()\n}","tryCatchPattern":"match find_worktree_git_dir(p) {\n    Err(e) if e.to_string().contains(\"no .git file or directory\") => {\n        eprintln!(\"{} is not a worktree; run 'git worktree add' first\", p.display());\n    }\n    Err(e) => return Err(e),\n    Ok(git_dir) => use(git_dir),\n}","preventionTips":["Always pass the worktree root, never a subdirectory.","Copy/rsync worktrees with dotfiles preserved (-a, no --exclude=.git).","Run `git worktree prune` to drop registrations for deleted checkouts.","Check `cat <path>/.git` points to a valid worktrees entry."],"tags":["git","filesystem","path-validation","rust"],"backgroundTag":"missing-git-directory","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}