golangci/golangci-lint · error
create destination file
Error message
create destination file: %w
What it means
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.
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
Example fix
// before
Builder{cfg: Config{Destination: ""}}
// after
Builder{cfg: Config{Destination: "/tmp/release"}} // created via os.MkdirAll in copyBinary Defensive patterns
Strategy: validation
Validate before calling
dest := cfg.Destination
if dest == "" { dest = "." }
if fi, err := os.Stat(dest); err != nil || !fi.IsDir() {
return fmt.Errorf("destination %s is not an existing directory", dest)
}
target := filepath.Join(dest, binaryName)
if fi, err := os.Lstat(target); err == nil && fi.IsDir() {
return fmt.Errorf("%s exists as a directory; remove it first", target)
} Try / catch
if err := b.copyBinary(name); err != nil {
var perr *fs.PathError
switch {
case errors.As(err, &perr) && errors.Is(perr, fs.ErrPermission):
log.Fatalf("cannot write %s: permission denied (chmod the directory or change Destination)", perr.Path)
default:
return err
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
AI-assisted analysis of golangci/golangci-lint@ed7a235d2d (2026-09-02).
Data as JSON: /api/errors/28b3b02598e35286.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/commands/internal/builder.go:231
}
defer func() { _ = source.Close() }()
info, err := source.Stat()
if err != nil {
return fmt.Errorf("stat source file: %w", err)
}
if b.cfg.Destination != "" {
err = os.MkdirAll(b.cfg.Destination, os.ModePerm)
if err != nil {
return fmt.Errorf("create destination directory: %w", err)
}
}
dst, err := os.OpenFile(filepath.Join(b.cfg.Destination, binaryName), os.O_RDWR|os.O_CREATE|os.O_TRUNC, info.Mode())
if err != nil {
return fmt.Errorf("create destination file: %w", err)
}
defer func() { _ = dst.Close() }()
_, err = io.Copy(dst, source)
if err != nil {
return fmt.Errorf("copy source to destination: %w", err)
}
return nil
}
func (b Builder) getBinaryName() string {
name := b.cfg.Name
if runtime.GOOS == "windows" {
name += ".exe"
}
View on GitHub (pinned to ed7a235d2d)