golang/go · error
build output %q already exists and is a directory
Error message
build output %q already exists and is a directory
What it means
Thrown by checkDstOverwrite when the requested build output path (`go build -o <path>`) already exists and is a directory. The go command refuses to overwrite/remove a directory to avoid destroying data, regardless of the -f/force setting.
Source
Thrown at src/cmd/go/internal/work/shell.go:253
}
// mayberemovefile removes a file only if it is a regular file
// When running as a user with sufficient privileges, we may delete
// even device files, for example, which is not intended.
func mayberemovefile(s string) {
if fi, err := os.Lstat(s); err == nil && !fi.Mode().IsRegular() {
return
}
os.Remove(s)
}
// Be careful about removing/overwriting dst.
// Do not remove/overwrite if dst exists and is a directory
// or a non-empty non-object file.
func checkDstOverwrite(dst string, force bool) error {
if fi, err := os.Stat(dst); err == nil {
if fi.IsDir() {
return fmt.Errorf("build output %q already exists and is a directory", dst)
}
if !force && fi.Mode().IsRegular() && fi.Size() != 0 && !isObject(dst) {
return fmt.Errorf("build output %q already exists and is not an object file", dst)
}
}
return nil
}
// writeFile writes the text to file.
func (sh *Shell) writeFile(file string, text []byte) error {
if cfg.BuildN || cfg.BuildX {
switch {
case len(text) == 0:
sh.ShowCmd("", "echo -n > %s # internal", file)
case bytes.IndexByte(text, '\n') == len(text)-1:
// One line. Use a simpler "echo" command.
sh.ShowCmd("", "echo '%s' > %s # internal", bytes.TrimSuffix(text, []byte("\n")), file)
default:View on GitHub (pinned to b6b368adc5)
Solutions
- Pick a different output name: `go build -o myapp-bin`.
- Remove or rename the existing directory: `rmdir myapp` (only if empty/unused).
- Build into the directory explicitly with a file path: `go build -o ./bin/myapp`.
Example fix
# before // mkdir myapp && go build -o myapp # after // go build -o ./bin/myapp
Defensive patterns
Strategy: validation
Validate before calling
// Ensure -o target is not an existing directory
out := flag.Arg(0)
if fi, err := os.Stat(out); err == nil && fi.IsDir() {
log.Fatalf("%s is a directory; choose a file path", out)
} Prevention
- Build into a dedicated ./bin directory with a file name.
- Avoid reusing module/subpackage names as -o targets.
- Document canonical output paths for your project.
When it happens
Trigger: Run `go build -o myapp` where `myapp` is an existing directory (e.g. you forgot the trailing slash, or a directory was created earlier by `mkdir myapp`). os.Stat reports IsDir, and checkDstOverwrite returns immediately.
Common situations: Typo where `-o app` collides with a source/module directory named `app`; CI that pre-creates an output directory; a previous `go build -o ./out` followed by `go build -o ./out` after `./out` became a folder; mirroring a Makefile target name that is also a dir.
Related errors
- build output %q already exists and is not an object file
- value is neither 'auto' nor a valid bool
- copying %s: %w
- copying %s to %s: %v
- %v is not a regular file
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/440903b382dcefe9.
Report an issue: GitHub.