golang/go · error
case-insensitive file name collision: %q and %q
Error message
case-insensitive file name collision: %q and %q
What it means
A package contains two input files whose names differ only by letter case (e.g., Foo.go and foo.go). The Go toolchain rejects this because case-insensitive filesystems (macOS APFS/HFS+ in default config, Windows NTFS) would treat them as the same file, causing unpredictable build behavior. The str.FoldDup function compares all file names from p.AllFiles() using Unicode case-folding.
Source
Thrown at src/cmd/go/internal/load/pkg.go:2030
if !opts.SuppressEmbedFiles {
p.EmbedFiles, p.Internal.Embed, err = resolveEmbed(p.Dir, p.EmbedPatterns)
if err != nil {
p.Incomplete = true
setError(err)
embedErr := err.(*EmbedError)
p.Error.setPos(p.Internal.Build.EmbedPatternPos[embedErr.Pattern])
}
}
// Check for case-insensitive collision of input files.
// To avoid problems on case-insensitive files, we reject any package
// where two different input files have equal names under a case-insensitive
// comparison.
inputs := p.AllFiles()
f1, f2 := str.FoldDup(inputs)
if f1 != "" {
setError(fmt.Errorf("case-insensitive file name collision: %q and %q", f1, f2))
return
}
// If first letter of input file is ASCII, it must be alphanumeric.
// This avoids files turning into flags when invoking commands,
// and other problems we haven't thought of yet.
// Also, _cgo_ files must be generated by us, not supplied.
// They are allowed to have //go:cgo_ldflag directives.
// The directory scan ignores files beginning with _,
// so we shouldn't see any _cgo_ files anyway, but just be safe.
for _, file := range inputs {
if !SafeArg(file) || strings.HasPrefix(file, "_cgo_") {
setError(fmt.Errorf("invalid input file name %q", file))
return
}
}
if name := pathpkg.Base(p.ImportPath); !SafeArg(name) {
setError(fmt.Errorf("invalid input directory name %q", name))View on GitHub (pinned to b6b368adc5)
Solutions
- Rename one of the colliding files to a distinctly different name.
- If the collision involves generated files (e.g., cgo outputs), check cgo directives and source file naming.
- Add a case-collision check to CI on case-sensitive systems (Linux) to catch issues before they reach macOS/Windows developers.
- Run go list -f '{{.GoFiles}} {{.CgoFiles}} {{.AllFiles}}' . to enumerate all input files.
Example fix
# before — case-only difference mv Foo.go foo.go # both Foo.go and foo.go exist # after — distinct names git mv foo.go foo_impl.go
Defensive patterns
Strategy: validation
Validate before calling
// Check for case-insensitive filename collisions in a directory.
func checkCaseCollisions(dir string) error {
entries, err := os.ReadDir(dir)
if err != nil {
return err
}
seen := make(map[string]string)
for _, e := range entries {
folded := strings.ToLower(e.Name())
if orig, ok := seen[folded]; ok {
return fmt.Errorf("case collision: %q and %q", orig, e.Name())
}
seen[folded] = e.Name()
}
return nil
} Prevention
- Run a case-collision check in CI on Linux before deploying to macOS/Windows.
- Use consistent casing conventions for all filenames (e.g., lowercase_with_underscores).
- Check for collisions after git merges and branch switches.
- Use go list -f '{{.AllFiles}}' . to enumerate all input files.
When it happens
Trigger: Two files in the same package directory with names that are equal under strings.EqualFold (Unicode case-insensitive comparison). FoldDup iterates the sorted list and returns the first colliding pair. p.AllFiles() includes Go files, C files, assembly files, and any other inputs — not just .go files.
Common situations: Developing on Linux (case-sensitive) but targeting macOS or Windows (case-insensitive). Git merges or file renames that accidentally create case-only differences. Files generated by different tools (cgo, protoc, etc.) that produce names differing only in case. Filesystem migrations between case-sensitive and case-insensitive volumes.
Related errors
- invalid package directory %q
- reading %s: %v
- disallowed import path %q
- invalid input file name %q
- invalid input directory name %q
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/b29b95c569098c6b.
Report an issue: GitHub.