golang/go · error
duplicate paths %s and %s in overlay map
Error message
duplicate paths %s and %s in overlay map
What it means
Returned by fsys.initFromJSON when two distinct source paths in the 'replace' map resolve (after abs()) to the same absolute path. The overlay system keys replacements by absolute path, so duplicates are ambiguous and rejected.
Source
Thrown at src/cmd/go/internal/fsys/fsys.go:375
}
return initFromJSON(b)
}
func initFromJSON(js []byte) error {
var ojs overlayJSON
if err := json.Unmarshal(js, &ojs); err != nil {
return fmt.Errorf("parsing overlay JSON: %v", err)
}
seen := make(map[string]string)
var list []replace
for _, from := range slices.Sorted(maps.Keys(ojs.Replace)) {
if from == "" {
return fmt.Errorf("empty string key in overlay map")
}
afrom := abs(from)
if old, ok := seen[afrom]; ok {
return fmt.Errorf("duplicate paths %s and %s in overlay map", old, from)
}
seen[afrom] = from
list = append(list, replace{from: afrom, to: abs(ojs.Replace[from])})
}
slices.SortFunc(list, func(x, y replace) int { return cmp(x.from, y.from) })
for i, r := range list {
if r.to == "" { // deleted
continue
}
// have file for r.from; look for child file implying r.from is a directory
prefix := r.from + string(filepath.Separator)
for _, next := range list[i+1:] {
if !strings.HasPrefix(next.from, prefix) {
break
}
if next.to != "" {View on GitHub (pinned to b6b368adc5)
Solutions
- Open the overlay JSON and keep only one spelling of each source path under 'replace'.
- Normalize every source path to absolute form (filepath.Abs) before emitting the overlay.
- Deduplicate by absolute path with a seen-map when generating overlays.
- Resolve symlinks (filepath.EvalSymlinks) before comparing if symlinks are involved.
Example fix
// before — two spellings of the same file
{ "replace": { "a.go": "x.go", "./a.go": "y.go" } }
// after — single canonical spelling
{ "replace": { "a.go": "x.go" } } Defensive patterns
Strategy: validation
Validate before calling
// Normalise and dedupe replace keys by absolute path before writing the overlay.
seen := make(map[string]string)
for from, to := range ojs.Replace {
if from == "" { continue }
absFrom, _ := filepath.Abs(from)
if prev, ok := seen[absFrom]; ok {
return fmt.Errorf("overlay has duplicate source paths %q and %q -> %s", prev, from, absFrom)
}
seen[absFrom] = from
_ = to
} Prevention
- Normalise every replace source to an absolute, symlink-evaluated path.
- Dedupe with a seen-map when generating overlays programmatically.
- Avoid mixing relative and absolute spellings of the same file.
When it happens
Trigger: An overlay with replace keys like "foo.go" and "./foo.go", or "a/b.go" alongside an absolute "/cwd/a/b.go", both producing the same abs path.
Common situations: Mixing relative and absolute spellings of the same path; symlinks where two different spellings collapse to one target; generators concatenating overlays without deduping.
Related errors
- reading overlay: %v
- parsing overlay JSON: %v
- empty string key in overlay map
- deleted in overlay
- cannot open directory in overlay
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/387997e5f61af3db.
Report an issue: GitHub.