golangci-lint: level=error msg=exit status 1: review gate failed on the PR
Fixes golangci-lint failing the PR gate with 'level=error msg=exit status 1'. Use when the lint step exits nonzero and blocks the review. Covers reproducing locally, fixing findings, and gating only on new issues so old debt does not block PRs. Not for golangci-lint crashes or config errors.
TL;DR
The linter found real issues and exited 1, which fails the gate. That is the gate working. Run the same command locally, fix the findings (or triage them deliberately), and consider gating only on issues introduced by the PR so pre-existing debt stops blocking new work.
The error
golangci-lint: level=error msg=exit status 1: review gate failed on the PRSteps
1. Reproduce the exact CI command locally
Run what CI runs, from the repo root:
golangci-lint run ./...Expected output: the same list of findings CI reported.
2. Read the findings, not just the exit code
The level=error msg=exit status 1 line is the wrapper. Scroll up for the per-issue lines naming files, lines, and linters. Expected output: a concrete list of issues to fix.
3. Fix the findings
Fix the code the linters flag. For deliberate exceptions, use a targeted nolint comment naming the specific linter, not a blanket suppression. Expected output: the finding count drops.
4. Gate only on new issues
To stop old debt from blocking PRs, limit the gate to issues on changed lines:
golangci-lint run --new-from-rev=origin/main ./...Expected output: only findings introduced by the PR fail the gate.
5. Verify a clean exit
Re-run the CI command locally until it exits 0, then push. Expected output: the gate passes on the PR.
When to use
- The exact exit-status-1 gate failure
- A new linter or enabled check starts failing PRs
- Legacy code failing a newly strict config
When not to use
- golangci-lint crashing (out of memory, panics)
- Config file errors (the run never starts)
- Version differences between local and CI
Tool compatibility
- golangci-lint v1.55 and later (v2 changed some flag names)
- Go 1.20 and later
- GitHub Actions and other CI runners
Variant phrasings
golangci-lint exit status 1 on PR
Same fix. Read the findings above the summary line.
golangci-lint failing only in CI
Check the version and the config path. CI may resolve a different config file than your local run.
how to ignore old golangci-lint issues
The new-from-rev flag in step 4 is the standard approach.
Why it happens
golangci-lint exits nonzero when any enabled linter reports an issue. CI treats nonzero as failure. The terse log line hides the actual findings, which is why the first step is always reproducing the full output locally.
Edge cases
- new-from-rev needs the base ref fetched. Shallow checkouts break it the same way they break reviewdog diffs.
- A blanket nolint without a linter name hides future issues too. Name the linter.
- Linter version skew: pin the golangci-lint version in CI so local and CI agree.
- Very large repos: the full run can be slow. The new-issues mode is faster as a side benefit.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_4Z0YEv7peGRWnSbV4ln5jw