golangci/golangci-lint · error

stat source file: %w

Error message

stat source file: %w

What it means

copyBinary calls source.Stat() after opening the binary to learn its mode bits for the destination file. This error wraps a failure of that stat call. Since the handle is already open, failure here is rare and usually indicates the file vanished mid-operation or an I/O error on the underlying filesystem.

Source

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

		return fmt.Errorf("%s: %w", strings.Join(cmd.Args, " "), err)
	}

	return nil
}

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 {

View on GitHub (pinned to ed7a235d2d)

Solutions

  1. Re-run the build — a transient race is the most common cause; ensure no concurrent process deletes the artifact
  2. Serialize build/copy steps so nothing cleans the output directory between go build and copyBinary
  3. Check filesystem health (dmesg / mount status) if the binary lives on a network or removable volume
  4. Inspect the wrapped *os.PathError errno to confirm which syscall/condition failed
Defensive patterns

Strategy: retry

Validate before calling

// pre-open sanity check
if _, err := os.Stat(filepath.Join(b.repo, binaryName)); err != nil {
    return fmt.Errorf("artifact vanished before copy: %w", err)
}

Try / catch

err := retry(3, func() error { return b.copyBinary(name) }) // safe: copy truncates dst
if err != nil {
    var perr *fs.PathError
    if errors.As(err, &perr) {
        log.Fatalf("stat failed on %s: %v — check for concurrent deletion or filesystem faults", perr.Path, perr.Err)
    }
    return err
}

Prevention

When it happens

Trigger: os.Open succeeded on b.repo/<binaryName> but source.Stat() returned an error: the file was removed or renamed after opening (delete-during-build race), the file sits on a failing/removable filesystem, or an unusual filesystem type rejects fstat.

Common situations: Concurrent builds cleaning the same output directory, CI where a later pipeline stage deletes artifacts early, network mounts (NFS) dropping stale handles, or /tmp cleanup daemons removing files mid-copy.

Related errors


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