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

  1. Open the overlay JSON and keep only one spelling of each source path under 'replace'.
  2. Normalize every source path to absolute form (filepath.Abs) before emitting the overlay.
  3. Deduplicate by absolute path with a seen-map when generating overlays.
  4. 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

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


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/387997e5f61af3db. Report an issue: GitHub.