{"record":{"id":"f7cdc3bbd3b00f77","repo":"golang/go","slug":"s-is-not-a-directory","errorCode":null,"errorMessage":"%s is not a directory","messagePattern":"(.+?) is not a directory","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/workcmd/use.go","lineNumber":143,"sourceCode":"\t\tif dup := keepDirs[absDir]; dup != \"\" && dup != dir {\n\t\t\tbase.Errorf(`go: already added \"%s\" as \"%s\"`, dir, dup)\n\t\t}\n\t\tkeepDirs[absDir] = dir\n\t}\n\n\tfor _, useDir := range args {\n\t\tabsArg, _ := pathRel(workDir, useDir)\n\n\t\tinfo, err := fsys.Stat(absArg)\n\t\tif err != nil {\n\t\t\t// Errors raised from os.Stat are formatted to be more user-friendly.\n\t\t\tif os.IsNotExist(err) {\n\t\t\t\terr = fmt.Errorf(\"directory %v does not exist\", base.ShortPath(absArg))\n\t\t\t}\n\t\t\tsw.Error(err)\n\t\t\tcontinue\n\t\t} else if !info.IsDir() {\n\t\t\tsw.Error(fmt.Errorf(\"%s is not a directory\", base.ShortPath(absArg)))\n\t\t\tcontinue\n\t\t}\n\n\t\tif !*useR {\n\t\t\tlookDir(useDir)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Add or remove entries for any subdirectories that still exist.\n\t\t// If the root itself is a symlink to a directory,\n\t\t// we want to follow it (see https://go.dev/issue/50807).\n\t\t// Add a trailing separator to force that to happen.\n\t\tfsys.WalkDir(str.WithFilePathSeparator(useDir), func(path string, d fs.DirEntry, err error) error {\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tif !d.IsDir() {","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/workcmd/use.go#L125-L161","documentation":"Thrown by `go work use` when fsys.Stat succeeds but info.IsDir() is false. The argument resolves to a regular file (or other non-directory entry), so it cannot be added as a workspace module directory. Reported via sw.Error and the loop continues to the next argument.","triggerScenarios":"Calling `go work use <file>` where <file> is a regular file (e.g. a .go source file, a go.mod file, a symlink to a file). The check at use.go:142 (`else if !info.IsDir()`) fires after a successful Stat.","commonSituations":"Pointing `go work use` at a go.mod file instead of its containing directory, dragging a file path from an editor, shell glob expanding to files, or following a tutorial that used the module file path rather than the directory.","solutions":["Pass the directory containing the module, not the go.mod file: `go work use ./mymod` instead of `go work use ./mymod/go.mod`.","Confirm with `test -d <path>` that the argument is a directory.","If using a symlink, ensure it points at a directory, not a file."],"exampleFix":"// before\ngo work use ./mymod/go.mod\n\n// after\ngo work use ./mymod","handlingStrategy":"validation","validationCode":"info, err := os.Stat(p)\nif err != nil {\n    return fmt.Errorf(\"%s: %w\", p, err)\n}\nif !info.IsDir() {\n    return fmt.Errorf(\"%s is a file, pass the containing directory\", p)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["In automation, strip trailing /go.mod and pass the parent directory.","Reject file arguments upstream with a quick IsDir check.","Document the 'pass the directory, not go.mod' rule in onboarding docs."],"tags":["go-work","filesystem","cli","path-validation"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}