golangci/golangci-lint · error
create destination directory: %w
Error message
create destination directory: %w
What it means
When cfg.Destination is set, copyBinary creates it (including parents) with os.MkdirAll(..., os.ModePerm) before writing the binary. This error wraps a MkdirAll failure, meaning the destination directory tree could not be created — typically a permissions or path problem (e.g. a non-directory file exists at a path component).
Source
Thrown at pkg/commands/internal/builder.go:225
func (b Builder) copyBinary(binaryName string) error {
src := filepath.Join(b.repo, binaryName)
source, err := os.Open(filepath.Clean(src))
if err != nil {
return fmt.Errorf("open source file: %w", err)
}
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
}
View on GitHub (pinned to ed7a235d2d)
Solutions
- Check each path component of cfg.Destination — rename/remove any regular file that occupies a directory name
- Verify write permission on the closest existing ancestor (or run with elevated privileges / pick a writable destination)
- Confirm the destination volume is not mounted read-only
- Correct the cfg.Destination value in the configuration to an absolute, valid directory path
- Read the wrapped *os.SyscallError: EACCES => permissions, ENOTDIR => file-in-path, EROFS => read-only
Example fix
// before destination: /usr/local/bin # needs root // after destination: ~/go/bin # writable without elevation
Defensive patterns
Strategy: validation
Validate before calling
if dest := cfg.Destination; dest != "" {
if fi, err := os.Stat(dest); err == nil && !fi.IsDir() {
return fmt.Errorf("destination %s exists and is not a directory", dest)
}
if err := os.MkdirAll(dest, 0o755); err != nil {
return fmt.Errorf("cannot create destination %s: %w", dest, err)
}
}
// also verify write access:
if dest != "" {
f, err := os.CreateTemp(dest, ".wcheck*")
if err != nil { return fmt.Errorf("destination %s not writable: %w", dest, err) }
f.Close(); os.Remove(f.Name())
} Try / catch
if err := b.copyBinary(name); err != nil {
var perr *fs.PathError
if errors.As(err, &perr) && errors.Is(perr, fs.ErrPermission) {
log.Fatalf("cannot create %s: permission denied — choose a writable destination or elevate", perr.Path)
}
return err
} Prevention
- Set Destination to an absolute directory path that already exists or is creatable
- Never point Destination at an existing regular file
- Prefer user-writable dirs (~/go/bin, bin/) over system paths needing root
- Check mount status if the destination may be read-only
When it happens
Trigger: cfg.Destination is non-empty and os.MkdirAll fails: parent path component is an existing regular file, no write permission on an ancestor directory, read-only filesystem, or an invalid/over-long path.
Common situations: Destination configured as an existing file instead of a directory, installing to /usr/local/bin without sudo, HOME misconfigured in CI containers, or a typo'd destination path landing on a read-only mount.
Understand the failure class
Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.
Related errors
- write file %s: %w
- failed to remove dir %s: %w
- create destination file: %w
- file %s open: %w
- read directory: %w
AI-assisted analysis of golangci/golangci-lint@ed7a235d2d (2026-09-02).
Data as JSON: /api/errors/3ee47587e44bd214.
Report an issue: GitHub.