#2322·go-git

Worktree checkout rejects Windows reserved device names (e.g. prn.sh) on Linux/macOS — regression since v5.19.1

Author: rramaCreated Aug 17, 2026Updated Sep 20, 2026

Worktree.Checkout (and therefore PlainClone) refuses to check out a file whose base name matches a Windows reserved device name (CON, PRN, AUX, NUL, COM1-9, LPT1-9), even on Linux/macOS where such names are valid. Real git has no such restriction on non-Windows platforms.

Regression: working in v5.19.0, broken in v5.19.1, still broken in v5.19.2 and main (at time of writing, b15e610f).

Code to reproduce (Linux/macOS)
go
package main

import (
	"os"
	"os/exec"

	git "github.com/go-git/go-git/v5"
)

func run(dir string, args ...string) {
	cmd := exec.Command("git", args...)
	cmd.Dir = dir
	cmd.Env = append(os.Environ(), "GIT_AUTHOR_NAME=t", "[email protected]",
		"GIT_COMMITTER_NAME=t", "[email protected]")
	if out, err := cmd.CombinedOutput(); err != nil {
		panic(string(out))
	}
}

func main() {
	src, _ := os.MkdirTemp("", "src")
	run(src, "init", "-q", "-b", "master")
	os.WriteFile(src+"/prn.sh", []byte("echo hi\n"), 0644)
	run(src, "add", "-A")
	run(src, "commit", "-q", "-m", "add prn.sh")

	_, err := git.PlainClone(os.TempDir()+"/dst", false, &git.CloneOptions{URL: src})
	if err != nil {
		panic(err) // invalid path: "prn.sh"
	}
}

Expected: clone succeeds — matches real git's behavior on Linux/macOS.

Actual: lstat: invalid path: "prn.sh" (or openfile: invalid path: ...).

Cause: worktreeFilesystem.validPath (worktree_fs.go) calls pathutil.WindowsValidPath, which rejects reserved device names unconditionally regardless of OS, gated only by core.protectNTFS — and defaultProtectNTFS() now hardcodes true on every platform. Real git's equivalent check (is_valid_win32_path) is compile-time restricted to Windows-native/Cygwin builds.

You already fixed this exact class of bug once: pathutil.ValidTreePath (the tree-read path) had the same unconditional reserved-name check and was scoped to Windows/Cygwin-only in ce4cca1861 ("align tree-path validation with upstream Git"). worktreeFilesystem.validPath — the checkout/write path — needs the same fix; it was missed.