golang/go · error · fs.PathError
overlay maps child %s to directory
Error message
overlay maps child %s to directory
What it means
During a ReadDir operation on the overlay filesystem, a child entry's replacement target (the 'actual' path on disk) is itself a directory. The overlay data model only supports file-to-file mappings — directory targets are explicitly rejected to avoid ambiguity between Lstat and Stat interactions with directories.
Source
Thrown at src/cmd/go/internal/fsys/fsys.go:485
for cname, cinfo := range info.children() {
if cinfo.dir {
all[cname] = fs.FileInfoToDirEntry(fakeDir(cname))
continue
}
if cinfo.deleted {
delete(all, cname)
continue
}
// Overlay is not allowed to have targets that are directories.
// And we hide symlinks, although it's not clear it helps callers.
cinfo, err := os.Stat(cinfo.actual)
if err != nil {
all[cname] = fs.FileInfoToDirEntry(missingFile(cname))
continue
}
if cinfo.IsDir() {
return nil, &fs.PathError{Op: "read", Path: name, Err: fmt.Errorf("overlay maps child %s to directory", cname)}
}
all[cname] = fs.FileInfoToDirEntry(fakeFile{cname, cinfo})
}
// Rebuild list using same storage.
dirs = dirs[:0]
for _, d := range all {
dirs = append(dirs, d)
}
slices.SortFunc(dirs, func(x, y fs.DirEntry) int { return strings.Compare(x.Name(), y.Name()) })
if len(dirs) == 0 {
return nil, dirErr
}
return dirs, nil
}
// Actual returns the actual file system path for the named file.View on GitHub (pinned to b6b368adc5)
Solutions
- Check the overlay JSON entry for the child path named in the error message — its target must be a regular file.
- Replace the directory target with a specific file path (e.g., '/real/src' -> '/real/src/main.go').
- If you need to overlay an entire directory tree, enumerate each file individually in the Replace map.
- Remove the overlay entry if the path should remain a directory on disk.
Example fix
// before — overlay target is a directory
{
"Replace": {
"/proj/pkg/main.go": "/real/pkg"
}
}
// after — overlay target is a file
{
"Replace": {
"/proj/pkg/main.go": "/real/pkg/main.go"
}
} Defensive patterns
Strategy: validation
Validate before calling
// Check that all overlay targets are regular files, not directories.
func validateOverlayTargets(entries map[string]string) error {
for from, to := range entries {
if to == "" {
continue
}
info, err := os.Stat(to)
if err != nil {
continue
}
if info.IsDir() {
return fmt.Errorf("overlay target %s -> %s is a directory", from, to)
}
}
return nil
} Prevention
- Ensure every overlay target points to a regular file on disk.
- Never point overlay entries at directory paths.
- Validate overlay targets with a pre-build script.
When it happens
Trigger: An overlay JSON Replace map entry points to a real path that is a directory. When go list, go build, or any tooling enumerates directory contents via fsys.ReadDir, it calls os.Stat on each child's 'actual' path; if that returns IsDir()==true, this error fires. The cname in the message is the virtual child path.
Common situations: Manually creating an overlay JSON and pointing a replacement target at a directory instead of a specific file. Misunderstanding that the overlay replaces individual files, not directory trees. Symlink targets in the overlay resolving to directories.
Related errors
- inconsistent files %s and %s in overlay map
- overlay maps to directory
- total length of command line and environment variables excee
- deleted in overlay
- cannot open directory in overlay
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/b83b6e6cc6b02996.
Report an issue: GitHub.