golangci/golangci-lint · error
create destination file: %w
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.
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)
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
- file %s open: %w
- open source file: %w
- stat source file: %w
- create destination directory: %w
- copy source to destination: %w
AI-assisted analysis of golangci/golangci-lint@ed7a235d2d (2026-09-02).
Data as JSON: /api/errors/28b3b02598e35286.
Report an issue: GitHub.