golang/go · error

copying %s: %w

Error message

copying %s: %w

What it means

Thrown by copyFile in the go build/install path when the destination file cannot be opened for writing (O_WRONLY|O_CREATE|O_TRUNC). On Windows a second attempt is made after moving the running binary aside; if that also fails, the wrapped error (referring to dst) is returned with the source path in the message.

Source

Thrown at src/cmd/go/internal/work/shell.go:225

		if _, err := os.Stat(dst + "~"); err == nil {
			os.Remove(dst + "~")
		}
	}

	mayberemovefile(dst)
	df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
	if err != nil && runtime.GOOS == "windows" {
		// Windows does not allow deletion of a binary file
		// while it is executing. Try to move it out of the way.
		// If the move fails, which is likely, we'll try again the
		// next time we do an install of this binary.
		if err := os.Rename(dst, dst+"~"); err == nil {
			os.Remove(dst + "~")
		}
		df, err = os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
	}
	if err != nil {
		return fmt.Errorf("copying %s: %w", src, err) // err should already refer to dst
	}

	_, err = io.Copy(df, sf)
	df.Close()
	if err != nil {
		mayberemovefile(dst)
		return fmt.Errorf("copying %s to %s: %v", src, dst, err)
	}
	return nil
}

// mayberemovefile removes a file only if it is a regular file
// When running as a user with sufficient privileges, we may delete
// even device files, for example, which is not intended.
func mayberemovefile(s string) {
	if fi, err := os.Lstat(s); err == nil && !fi.Mode().IsRegular() {
		return
	}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Check write permission on the destination directory: `ls -ld $(dirname <dst>)`.
  2. Free disk space if full: `df -h`.
  3. On Windows, close any process running the previous binary, then rebuild.
  4. Fix ownership/permissions or pick a writable GOBIN: `go install -o /tmp/bin/app`.

Example fix

# before
// go install ./...   (GOBIN not writable)

# after
// sudo chown -R $USER ~/go/bin && go install ./...
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure the install destination is writable before building
dst := filepath.Join(os.Getenv("GOBIN"), "app")
if fi, err := os.Stat(filepath.Dir(dst)); err != nil || !fi.IsDir() {
    log.Fatalf("GOBIN dir not usable: %v", err)
}
if err := os.WriteFile(dst+".probe", []byte{}, 0644); err != nil {
    log.Fatalf("cannot write to %s: %v", filepath.Dir(dst), err)
}
os.Remove(dst + ".probe")

Try / catch

// Wrap go build/install and surface a clear message
err := sh.copyFile(src, dst)
if err != nil {
    if errors.Is(err, fs.ErrPermission) {
        return fmt.Errorf("permission denied writing %s: check ownership/GOBIN", dst)
    }
    if errors.Is(err, fs.ErrNotExist) {
        return fmt.Errorf("destination dir missing: %s", filepath.Dir(dst))
    }
    return fmt.Errorf("copy failed: %w", err)
}

Prevention

When it happens

Trigger: Run `go install` / `go build -o` to a destination that is read-only, on a full disk, in a directory without write permission, or held open by another process (and on non-Windows there is no rename-aside retry). os.OpenFile fails and the error is wrapped as `copying <src>: <err>`.

Common situations: Installing into a GOBIN owned by root without sudo; destination on a read-only filesystem; ENOSPC (disk full); SELinux/AppArmor denying the write; antivirus or indexer holding the file (Windows).

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/be7ffc9d2c506b6b. Report an issue: GitHub.