golangci/golangci-lint · error
can't read from patch file %s: %w
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.
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)
Solutions
- Verify the patch file path exists and is spelled correctly
- Ensure the patch file is created before golangci-lint runs (e.g. git diff > patch.txt in an earlier CI step)
- Check file permissions / that the file is mounted into the container
- 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
- Generate the patch file in an earlier, guaranteed CI step
- Pass the patch inline via --patch when the file lifecycle is hard to control
- Mount patch files explicitly in containers and verify with ls in CI
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
- reading go.mod file: %w
- unable to open file %s: %w
- got no diffs from patch parser: %s
- %s: %w
- the configuration contains invalid elements
AI-assisted analysis of golangci/golangci-lint@ed7a235d2d (2026-09-02).
Data as JSON: /api/errors/cdc89820b45d6b6b.
Report an issue: GitHub.