tailscale/tailscale · error
finding git root: %w
Error message
finding git root: %w
What it means
mkversion.InfoFrom runs `git rev-parse --show-toplevel` in the directory you pass (empty string = cwd) to locate the git checkout it derives version strings from. This error means that command failed: the directory is not inside a git work tree, the .git directory is corrupt, or git could not run at all. The wrapped error (usually a dirRunner 'running [git rev-parse --show-toplevel]...' message) carries git's own 'fatal: not a git repository' diagnostics.
Source
Thrown at version/mkversion/mkversion.go:122
}
// Info constructs a VersionInfo from the current working directory and returns
// it, or terminates the process via log.Fatal.
func Info() VersionInfo {
v, err := InfoFrom("")
if err != nil {
log.Fatal(err)
}
return v
}
// InfoFrom constructs a VersionInfo from dir and returns it, or an error.
func InfoFrom(dir string) (VersionInfo, error) {
runner := dirRunner(dir)
gitRoot, err := runner.output("git", "rev-parse", "--show-toplevel")
if err != nil {
return VersionInfo{}, fmt.Errorf("finding git root: %w", err)
}
runner = dirRunner(gitRoot)
modBs, err := os.ReadFile(filepath.Join(gitRoot, "go.mod"))
if err != nil {
return VersionInfo{}, fmt.Errorf("reading go.mod: %w", err)
}
modPath := modfile.ModulePath(modBs)
if modPath == "" {
return VersionInfo{}, fmt.Errorf("no module path in go.mod")
}
if modPath == "tailscale.com" {
// Invoked in the tailscale.com repo directly, just no further info to
// collect.
v, err := infoFromDir(gitRoot)
if err != nil {
return VersionInfo{}, errView on GitHub (pinned to 6e0912f979)
Solutions
- Run the build from the root of a git clone and verify with `git rev-parse --show-toplevel` that it prints the expected path
- If git is not installed (see a 'running [git ...]' wrapper mentioning exec/not-found), install git and ensure it is on PATH
- Repair the checkout: confirm `git status` works; if .git is corrupt, re-clone
- Pass a directory that is actually inside the repository instead of a temp/output directory
Example fix
# before: building from an unpacked tarball
mkversion.InfoFrom("/build/tailscale-src") # no .git -> finding git root: ...
# after: build from a real clone
$ git clone https://github.com/tailscale/tailscale /build/tailscale
mkversion.InfoFrom("/build/tailscale") Defensive patterns
Strategy: validation
Validate before calling
// Verify dir is inside a git work tree before calling mkversion.InfoFrom.
func inGitRepo(dir string) bool {
cmd := exec.Command("git", "-C", dir, "rev-parse", "--show-toplevel")
return cmd.Run() == nil
}
if !inGitRepo(buildDir) {
log.Fatalf("%s is not a git checkout; run the build from a clone", buildDir)
}
v, err := mkversion.InfoFrom(buildDir) Type guard
func isGitRootError(err error) bool {
return err != nil && strings.Contains(err.Error(), "finding git root:")
} Try / catch
v, err := mkversion.InfoFrom(dir)
if err != nil {
if isGitRootError(err) {
log.Fatalf("run the build from a git checkout: %v", err)
}
return fmt.Errorf("mkversion: %w", err)
} Prevention
- Always build from a git clone, never from an exported tarball
- Install git in CI images and assert `git --version` before the build step
- Log the cwd before invoking mkversion so bad build directories are obvious
When it happens
Trigger: Calling mkversion.Info() or InfoFrom(dir) with dir outside any git repository, with a broken/missing .git directory, or in an environment where the git binary is missing from PATH (surfaced via the 2076-style 'running %v' wrapper).
Common situations: Running the tailscale build/version-stamping step from an exported source tarball, from the wrong directory in CI, or inside a minimal container that lacks git or has HOME unset so git cannot be found.
Related errors
- getting git hash: %w
- getting git date: %w
- reading go.mod: %w
- no module path in go.mod
- no require tailscale.com line in go.mod
AI-assisted analysis of tailscale/tailscale@6e0912f979 (2026-08-18).
Data as JSON: /api/errors/40390e8825c65215.
Report an issue: GitHub.