golangci/golangci-lint · error

copy source to destination: %w

Error message

copy source to destination: %w

What it means

copyBinary streams the binary with io.Copy(dst, source); this error wraps any failure of that copy. Since both handles are already open, failures come from the write side (disk full, quota) or the read side (source became unreadable), plus any flush/write error at the OS level.

Source

Thrown at pkg/commands/internal/builder.go:238

	}

	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"
	}

	return name
}

func (b Builder) createVersion(orig string) (string, error) {
	hash := sha256.New()

	for _, plugin := range b.cfg.Plugins {

View on GitHub (pinned to ed7a235d2d)

Solutions

  1. Free disk space on the destination volume (df -h) or point Destination at a volume with enough room
  2. Check the source binary size and integrity; rebuild if it may be truncated
  3. Re-run the copy after resolving the I/O condition — the destination file is truncated by O_TRUNC so a retry is safe
  4. Check quotas (quota -s) and process limits (ulimit -f) if writes stop at a consistent size
  5. Inspect the wrapped error: it names the failing side (read from source vs write to dst path)

Example fix

// before
# destination volume 95% full during release
// after
df -h /release && go build clean && retry Build with Destination on a volume with free space
Defensive patterns

Strategy: retry

Validate before calling

src := filepath.Join(b.repo, binaryName)
info, err := os.Stat(src)
if err != nil { return err }
var st syscall.Statfs_t
if err := syscall.Statfs(cfg.Destination, &st); err == nil {
    free := st.Bavail * uint64(st.Bsize)
    if free < uint64(info.Size())*2 {
        return fmt.Errorf("only %d bytes free at %s, need ~%d", free, cfg.Destination, info.Size()*2)
    }
}

Try / catch

err := retry(3, backoffExponential, func() error {
    return b.copyBinary(name) // O_TRUNC makes each attempt start clean
})
if err != nil {
    log.Fatalf("copy failed after retries: %v — check disk space and quotas", err)
}

Prevention

When it happens

Trigger: io.Copy returned an error mid-transfer: destination filesystem full or over quota, source file truncated/replaced during read, I/O error on either volume, or process resource limits (RLIMIT_FSIZE) hit while writing.

Common situations: CI runner with small ephemeral disk copying large binaries, quota-limited home directories, NFS/network destination dropping mid-write, or disk-full during a release upload step.

Related errors


AI-assisted analysis of golangci/golangci-lint@ed7a235d2d (2026-09-02). Data as JSON: /api/errors/5cbd0f224fc511c1. Report an issue: GitHub.