{"record":{"id":"440903b382dcefe9","repo":"golang/go","slug":"build-output-q-already-exists-and-is-a-directory","errorCode":null,"errorMessage":"build output %q already exists and is a directory","messagePattern":"build output %q already exists and is a directory","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/work/shell.go","lineNumber":253,"sourceCode":"}\n\n// mayberemovefile removes a file only if it is a regular file\n// When running as a user with sufficient privileges, we may delete\n// even device files, for example, which is not intended.\nfunc mayberemovefile(s string) {\n\tif fi, err := os.Lstat(s); err == nil && !fi.Mode().IsRegular() {\n\t\treturn\n\t}\n\tos.Remove(s)\n}\n\n// Be careful about removing/overwriting dst.\n// Do not remove/overwrite if dst exists and is a directory\n// or a non-empty non-object file.\nfunc checkDstOverwrite(dst string, force bool) error {\n\tif fi, err := os.Stat(dst); err == nil {\n\t\tif fi.IsDir() {\n\t\t\treturn fmt.Errorf(\"build output %q already exists and is a directory\", dst)\n\t\t}\n\t\tif !force && fi.Mode().IsRegular() && fi.Size() != 0 && !isObject(dst) {\n\t\t\treturn fmt.Errorf(\"build output %q already exists and is not an object file\", dst)\n\t\t}\n\t}\n\treturn nil\n}\n\n// writeFile writes the text to file.\nfunc (sh *Shell) writeFile(file string, text []byte) error {\n\tif cfg.BuildN || cfg.BuildX {\n\t\tswitch {\n\t\tcase len(text) == 0:\n\t\t\tsh.ShowCmd(\"\", \"echo -n > %s # internal\", file)\n\t\tcase bytes.IndexByte(text, '\\n') == len(text)-1:\n\t\t\t// One line. Use a simpler \"echo\" command.\n\t\t\tsh.ShowCmd(\"\", \"echo '%s' > %s # internal\", bytes.TrimSuffix(text, []byte(\"\\n\")), file)\n\t\tdefault:","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/work/shell.go#L235-L271","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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`."],"exampleFix":"# before\n// mkdir myapp && go build -o myapp\n\n# after\n// go build -o ./bin/myapp","handlingStrategy":"validation","validationCode":"// Ensure -o target is not an existing directory\nout := flag.Arg(0)\nif fi, err := os.Stat(out); err == nil && fi.IsDir() {\n    log.Fatalf(\"%s is a directory; choose a file path\", out)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["go-toolchain","build","filesystem","validation"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}