{"record":{"id":"28b3b02598e35286","repo":"golangci/golangci-lint","slug":"create-destination-file-w","errorCode":null,"errorMessage":"create destination file: %w","messagePattern":"create destination file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/commands/internal/builder.go","lineNumber":231,"sourceCode":"\t}\n\n\tdefer func() { _ = source.Close() }()\n\n\tinfo, err := source.Stat()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"stat source file: %w\", err)\n\t}\n\n\tif b.cfg.Destination != \"\" {\n\t\terr = os.MkdirAll(b.cfg.Destination, os.ModePerm)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"create destination directory: %w\", err)\n\t\t}\n\t}\n\n\tdst, err := os.OpenFile(filepath.Join(b.cfg.Destination, binaryName), os.O_RDWR|os.O_CREATE|os.O_TRUNC, info.Mode())\n\tif err != nil {\n\t\treturn fmt.Errorf(\"create destination file: %w\", err)\n\t}\n\n\tdefer func() { _ = dst.Close() }()\n\n\t_, err = io.Copy(dst, source)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"copy source to destination: %w\", err)\n\t}\n\n\treturn nil\n}\n\nfunc (b Builder) getBinaryName() string {\n\tname := b.cfg.Name\n\tif runtime.GOOS == \"windows\" {\n\t\tname += \".exe\"\n\t}\n","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/golangci/golangci-lint/blob/ed7a235d2d771152056fdc142a9855567c5796a9/pkg/commands/internal/builder.go#L213-L249","documentation":"copyBinary creates the destination file with os.OpenFile(filepath.Join(b.cfg.Destination, binaryName), O_RDWR|O_CREATE|O_TRUNC, info.Mode()) and this error wraps that call's failure. The file could not be created or opened for writing at the destination path, using the source binary's permission bits.","triggerScenarios":"Destination directory exists (or was just created) but OpenFile fails: no write permission in the directory, the target name exists as a directory, destination path is wrong so filepath.Join lands in a nonexistent directory (only possible when Destination == \"\" resolving to a relative path), disk full is not typical at create time but EACCES/ENOTDIR/EISDIR are.","commonSituations":"Installing over an existing directory named like the binary, running as non-root against a system bin directory, Destination left empty so the join resolves relative to CWD which doesn't exist, or SELinux/AppArmor blocking writes.","solutions":["Ensure cfg.Destination is set to an existing writable directory before Build","Check write permission on the destination directory (ls -ld); chmod or choose another directory","Check whether a directory already exists at filepath.Join(destination, binaryName) and remove/rename it","If Destination is intentionally empty, run Build from the intended working directory or set Destination explicitly","Inspect the wrapped errno: EACCES => permissions, EISDIR => target is a directory, ENOENT => bad destination path"],"exampleFix":"// before\nBuilder{cfg: Config{Destination: \"\"}}\n// after\nBuilder{cfg: Config{Destination: \"/tmp/release\"}} // created via os.MkdirAll in copyBinary","handlingStrategy":"validation","validationCode":"dest := cfg.Destination\nif dest == \"\" { dest = \".\" }\nif fi, err := os.Stat(dest); err != nil || !fi.IsDir() {\n    return fmt.Errorf(\"destination %s is not an existing directory\", dest)\n}\ntarget := filepath.Join(dest, binaryName)\nif fi, err := os.Lstat(target); err == nil && fi.IsDir() {\n    return fmt.Errorf(\"%s exists as a directory; remove it first\", target)\n}","typeGuard":null,"tryCatchPattern":"if err := b.copyBinary(name); err != nil {\n    var perr *fs.PathError\n    switch {\n    case errors.As(err, &perr) && errors.Is(perr, fs.ErrPermission):\n        log.Fatalf(\"cannot write %s: permission denied (chmod the directory or change Destination)\", perr.Path)\n    default:\n        return err\n    }\n}","preventionTips":["Always configure Destination explicitly; never rely on empty-Destination CWD resolution","Ensure the destination directory is writable by the executing user","Check for a directory colliding with the binary name before installing","On locked-down systems verify no LSM (SELinux/AppArmor) blocks writes to the target"],"tags":["go","file-io","openfile","permissions"],"backgroundTag":"permission-denied","analyzedSha":"ed7a235d2d771152056fdc142a9855567c5796a9","analyzedAt":"2026-09-02T18:47:33.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}