golang/go · error

inconsistent files %s and %s in overlay map

Error message

inconsistent files %s and %s in overlay map

What it means

The Go overlay filesystem (enabled via -overlay flag pointing to a JSON file) maps virtual paths to real files. This error fires during overlay initialization when a path is mapped as a file (has a non-empty 'to' target) while simultaneously having a child path also mapped as a file, implying the parent is a directory. A single path cannot be both a file and a directory, so the overlay is rejected as internally inconsistent.

Source

Thrown at src/cmd/go/internal/fsys/fsys.go:395

		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 != "" {
				// found child file
				return fmt.Errorf("inconsistent files %s and %s in overlay map", r.from, next.from)
			}
		}
	}

	overlay = list
	return nil
}

// IsDir returns true if path is a directory on disk or in the
// overlay.
func IsDir(path string) (bool, error) {
	Trace("IsDir", path)

	switch info := stat(path); {
	case info.dir:
		return true, nil
	case info.deleted, info.replaced:
		return false, nil

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Inspect the two paths named in the error — the parent is treated as both a file and a directory in the overlay JSON.
  2. If the parent should be a file, remove child entries that place files beneath it (e.g., delete the '/proj/foo.go/bar.go' entry).
  3. If the parent should be a directory, ensure the parent entry itself is not mapped to a file target — either remove it or mark it as deleted (empty 'to').
  4. Regenerate the overlay JSON from scratch, ensuring each replaced path is unambiguously a file or deleted.

Example fix

// before — overlay JSON is inconsistent
{
  "Replace": {
    "/proj/main.go": "/real/main.go",
    "/proj/main.go/util.go": "/real/util.go"
  }
}
// after — main.go is a file only
{
  "Replace": {
    "/proj/main.go": "/real/main.go"
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate overlay JSON for parent/child file conflicts before use.
func validateOverlay(entries map[string]string) error {
    var paths []string
    for from, to := range entries {
        if to != "" {
            paths = append(paths, from)
        }
    }
    sort.Strings(paths)
    for i, a := range paths {
        prefix := a + string(filepath.Separator)
        for _, b := range paths[i+1:] {
            if !strings.HasPrefix(b, prefix) {
                break
            }
            return fmt.Errorf("inconsistent overlay: %s is both file and parent of %s", a, b)
        }
    }
    return nil
}

Prevention

When it happens

Trigger: Passing -overlay=overlay.json where the Replace map contains both '/proj/foo.go' -> '/real/foo.go' and '/proj/foo.go/bar.go' -> '/real/bar.go'. The first entry treats foo.go as a file; the second implies it is a directory containing bar.go. The sorted-path scan in initFromJSON detects this parent/child conflict.

Common situations: Hand-editing overlay JSON files for test harnesses or IDE integration. Automated overlay generators that don't validate parent/child relationships. Copying overlay entries between different directory layouts where a path changes from directory to file. Mistakenly replacing a path that should be a directory with a file mapping.

Related errors


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