golang/go · error
%s is not a directory
Error message
%s is not a directory
What it means
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.
Source
Thrown at src/cmd/go/internal/workcmd/use.go:143
if dup := keepDirs[absDir]; dup != "" && dup != dir {
base.Errorf(`go: already added "%s" as "%s"`, dir, dup)
}
keepDirs[absDir] = dir
}
for _, useDir := range args {
absArg, _ := pathRel(workDir, useDir)
info, err := fsys.Stat(absArg)
if err != nil {
// Errors raised from os.Stat are formatted to be more user-friendly.
if os.IsNotExist(err) {
err = fmt.Errorf("directory %v does not exist", base.ShortPath(absArg))
}
sw.Error(err)
continue
} else if !info.IsDir() {
sw.Error(fmt.Errorf("%s is not a directory", base.ShortPath(absArg)))
continue
}
if !*useR {
lookDir(useDir)
continue
}
// Add or remove entries for any subdirectories that still exist.
// If the root itself is a symlink to a directory,
// we want to follow it (see https://go.dev/issue/50807).
// Add a trailing separator to force that to happen.
fsys.WalkDir(str.WithFilePathSeparator(useDir), func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if !d.IsDir() {View on GitHub (pinned to b6b368adc5)
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.
Example fix
// before go work use ./mymod/go.mod // after go work use ./mymod
Defensive patterns
Strategy: validation
Validate before calling
info, err := os.Stat(p)
if err != nil {
return fmt.Errorf("%s: %w", p, err)
}
if !info.IsDir() {
return fmt.Errorf("%s is a file, pass the containing directory", p)
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- directory %v does not exist
- reading go.work: %w
- file is empty
- deleted in overlay
- cannot open directory in overlay
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/f7cdc3bbd3b00f77.
Report an issue: GitHub.