golangci/golangci-lint · error

can't read from patch file

Error message

can't read from patch file %s: %w

What it means

The diff processor cannot read the patch file given via the --patch or patch-file option. os.ReadFile fails and the error is wrapped with the offending file path so the developer knows which patch input is broken. Without a patch, golangci-lint cannot compute which lines changed, so processing cannot continue.

Solutions

  1. Verify the patch file path exists and is spelled correctly
  2. Ensure the patch file is created before golangci-lint runs (e.g. git diff > patch.txt in an earlier CI step)
  3. Check file permissions / that the file is mounted into the container
  4. Alternatively pass the patch inline via --patch instead of a file

Example fix

// before
p := diff.NewPatchProcessor(diff.WithPatchFilePath("./patches/current.diff"))
// after
if _, err := os.Stat("./patches/current.diff"); err != nil { log.Fatal(err) }
p := diff.NewPatchProcessor(diff.WithPatchFilePath("./patches/current.diff"))
Defensive patterns

Strategy: validation

Validate before calling

// Go: stat the patch file before constructing the processor
if _, err := os.Stat(patchPath); err != nil {
    return fmt.Errorf("patch file missing: %w", err)
}

Try / catch

issues, err := p.Process(issues)
if err != nil {
    var pe *os.PathError
    if errors.As(err, &pe) { log.Fatalf("patch input problem: %v", err) }
    return err
}

Prevention

When it happens

Trigger: Process is called with ProcessorOption patchFilePath set to a path that does not exist, is a directory, or is unreadable (permissions).

Common situations: Typoed path in --patch CI argument; patch file generated in a previous CI step that didn't run; running in a container where the patch was not mounted; permissions after downloading the patch as another user.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at pkg/result/processors/diff.go:61

		patch:         os.Getenv(envGolangciDiffProcessorPatch),
	}
}

func (*Diff) Name() string {
	return "diff"
}

func (p *Diff) Process(issues []*result.Issue) ([]*result.Issue, error) {
	if !p.onlyNew && p.fromRev == "" && p.fromMergeBase == "" && p.patchFilePath == "" && p.patch == "" {
		return issues, nil
	}

	var patchReader io.Reader
	switch {
	case p.patchFilePath != "":
		patch, err := os.ReadFile(p.patchFilePath)
		if err != nil {
			return nil, fmt.Errorf("can't read from patch file %s: %w", p.patchFilePath, err)
		}

		patchReader = bytes.NewReader(patch)

	case p.patch != "":
		patchReader = strings.NewReader(p.patch)
	}

	checker := revgrep.Checker{
		Patch:        patchReader,
		RevisionFrom: p.fromRev,
		MergeBase:    p.fromMergeBase,
		WholeFiles:   p.wholeFiles,
	}

	err := checker.Prepare(context.Background())
	if err != nil {
		return nil, fmt.Errorf("can't prepare diff by revgrep: %w", err)

View on GitHub (pinned to ed7a235d2d)