{"record":{"id":"086efda56542383f","repo":"golang/go","slug":"replacement-directory-s-w","errorCode":null,"errorMessage":"replacement directory %s: %w","messagePattern":"replacement directory (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/modload/import.go","lineNumber":811,"sourceCode":"\t\t\tdir = r.Path\n\t\t\tif !filepath.IsAbs(dir) {\n\t\t\t\tdir = filepath.Join(replaceRelativeTo(ld), dir)\n\t\t\t}\n\t\t\t// Ensure that the replacement directory actually exists:\n\t\t\t// dirInModule does not report errors for missing modules,\n\t\t\t// so if we don't report the error now, later failures will be\n\t\t\t// very mysterious.\n\t\t\tif _, err := fsys.Stat(dir); err != nil {\n\t\t\t\t// TODO(bcmills): We should also read dir/go.mod here and check its Go version,\n\t\t\t\t// and return a gover.TooNewError if appropriate.\n\n\t\t\t\tif os.IsNotExist(err) {\n\t\t\t\t\t// Semantically the module version itself “exists” — we just don't\n\t\t\t\t\t// have its source code. Remove the equivalence to os.ErrNotExist,\n\t\t\t\t\t// and make the message more concise while we're at it.\n\t\t\t\t\terr = fmt.Errorf(\"replacement directory %s does not exist\", r.Path)\n\t\t\t\t} else {\n\t\t\t\t\terr = fmt.Errorf(\"replacement directory %s: %w\", r.Path, err)\n\t\t\t\t}\n\t\t\t\treturn dir, true, module.VersionError(mod, err)\n\t\t\t}\n\t\t\treturn dir, true, nil\n\t\t}\n\t\tmod = r\n\t}\n\n\tif mustHaveSums(ld) && !modfetch.HaveSum(ld.Fetcher(), mod) {\n\t\treturn \"\", false, module.VersionError(mod, &sumMissingError{})\n\t}\n\n\tdir, err = ld.Fetcher().Download(ctx, mod)\n\treturn dir, false, err\n}\n\n// mustHaveSums reports whether we require that all checksums\n// needed to load or build packages are already present in the go.sum file.","sourceCodeStart":793,"sourceCodeEnd":829,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/modload/import.go#L793-L829","documentation":"Sibling of 1063: a local replace directory failed fsys.Stat for a reason OTHER than os.ErrNotExist (e.g. permission denied, I/O error). The original error is wrapped with %w so it can be unwrapped by callers. Carried through module.VersionError so the offending module version is identified.","triggerScenarios":"go.mod has a local replace directive and fsys.Stat(dir) returns a non-NotExist error: EACCES (permission denied), EIO, a broken symlink, or a path crossing an unreadable mount.","commonSituations":"Replace target on a mounted volume that is not mounted; file mode / ownership blocks the Go process; dangling symlink in the replace path; container where the bind-mount is missing.","solutions":["Check permissions on every component of the path: chmod/chown so the Go process can stat it.","Repair or remove dangling symlinks in the replace path.","Verify the volume/mount holding the target is actually mounted in CI containers.","Point the replace at a readable location, or switch to a versioned replace."],"exampleFix":"// before\nreplace example.com/foo => /mnt/foo   // /mnt/foo: permission denied\n// error: replacement directory /mnt/foo: permission denied\n\n// after\n$ sudo chown -R $USER /mnt/foo    // or fix the mount / mode\n$ go build ./...","handlingStrategy":"validation","validationCode":"// Validate local replace targets are stat-able (not just present).\ndata, _ := os.ReadFile(\"go.mod\")\nf, _ := modfile.Parse(\"go.mod\", data, nil)\nfor _, r := range f.Replace {\n    if r.New.Version == \"\" {\n        if _, err := os.Stat(r.New.Path); err != nil && !os.IsNotExist(err) {\n            return fmt.Errorf(\"replace target %s unreadable: %w\", r.New.Path, err)\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"out, err := exec.Command(\"go\", \"build\", \"./...\").CombinedOutput()\nif err != nil && bytes.Contains(out, []byte(\"replacement directory\")) {\n    // Could be 1063 (missing) or 1064 (perm/io). Surface wrapped cause.\n    var pathErr *os.PathError\n    if errors.As(errors.Unwrap(err), &pathErr) {\n        log.Printf(\"fix permissions on %s: %v\", pathErr.Path, pathErr.Err)\n    }\n    return err\n}\nreturn err","preventionTips":["Ensure the Go process has read+execute on every path component of replace targets.","In containers, verify bind-mounts for replace targets before building.","Avoid replace paths that traverse temp or removable media.","Pre-build check: os.Stat each local replace path."],"tags":["replace-directive","local-replace","filesystem","permissions","io-error"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}