{"record":{"id":"b83b6e6cc6b02996","repo":"golang/go","slug":"overlay-maps-child-s-to-directory","errorCode":null,"errorMessage":"overlay maps child %s to directory","messagePattern":"overlay maps child (.+?) to directory","errorType":"validation","errorClass":"fs.PathError","httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/fsys/fsys.go","lineNumber":485,"sourceCode":"\tfor cname, cinfo := range info.children() {\n\t\tif cinfo.dir {\n\t\t\tall[cname] = fs.FileInfoToDirEntry(fakeDir(cname))\n\t\t\tcontinue\n\t\t}\n\t\tif cinfo.deleted {\n\t\t\tdelete(all, cname)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Overlay is not allowed to have targets that are directories.\n\t\t// And we hide symlinks, although it's not clear it helps callers.\n\t\tcinfo, err := os.Stat(cinfo.actual)\n\t\tif err != nil {\n\t\t\tall[cname] = fs.FileInfoToDirEntry(missingFile(cname))\n\t\t\tcontinue\n\t\t}\n\t\tif cinfo.IsDir() {\n\t\t\treturn nil, &fs.PathError{Op: \"read\", Path: name, Err: fmt.Errorf(\"overlay maps child %s to directory\", cname)}\n\t\t}\n\t\tall[cname] = fs.FileInfoToDirEntry(fakeFile{cname, cinfo})\n\t}\n\n\t// Rebuild list using same storage.\n\tdirs = dirs[:0]\n\tfor _, d := range all {\n\t\tdirs = append(dirs, d)\n\t}\n\tslices.SortFunc(dirs, func(x, y fs.DirEntry) int { return strings.Compare(x.Name(), y.Name()) })\n\n\tif len(dirs) == 0 {\n\t\treturn nil, dirErr\n\t}\n\treturn dirs, nil\n}\n\n// Actual returns the actual file system path for the named file.","sourceCodeStart":467,"sourceCodeEnd":503,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/fsys/fsys.go#L467-L503","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before — overlay target is a directory\n{\n  \"Replace\": {\n    \"/proj/pkg/main.go\": \"/real/pkg\"\n  }\n}\n// after — overlay target is a file\n{\n  \"Replace\": {\n    \"/proj/pkg/main.go\": \"/real/pkg/main.go\"\n  }\n}","handlingStrategy":"validation","validationCode":"// Check that all overlay targets are regular files, not directories.\nfunc validateOverlayTargets(entries map[string]string) error {\n    for from, to := range entries {\n        if to == \"\" {\n            continue\n        }\n        info, err := os.Stat(to)\n        if err != nil {\n            continue\n        }\n        if info.IsDir() {\n            return fmt.Errorf(\"overlay target %s -> %s is a directory\", from, to)\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["go","go-toolchain","overlay","fsys","configuration"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}