golangci/golangci-lint · error
failed to pre-run %s: %w
Error message
failed to pre-run %s: %w
What it means
golangci-lint's MetaLinter.Run wraps any error returned by an individual linter's preRun hook. preRun is executed once per enabled linter before analysis (e.g. to build package maps or load type information). The %w preserves the underlying cause; the %s names which linter failed.
Source
Thrown at pkg/goanalysis/metalinter.go:27
"github.com/golangci/golangci-lint/v2/pkg/lint/linter"
"github.com/golangci/golangci-lint/v2/pkg/result"
)
type MetaLinter struct {
linters []*Linter
analyzerToLinterName map[*analysis.Analyzer]string
}
func NewMetaLinter(linters []*Linter) *MetaLinter {
ml := &MetaLinter{linters: linters}
ml.analyzerToLinterName = ml.getAnalyzerToLinterNameMapping()
return ml
}
func (ml MetaLinter) Run(_ context.Context, lintCtx *linter.Context) ([]*result.Issue, error) {
for _, l := range ml.linters {
if err := l.preRun(lintCtx); err != nil {
return nil, fmt.Errorf("failed to pre-run %s: %w", l.Name(), err)
}
}
return runAnalyzers(ml, lintCtx)
}
func (MetaLinter) Name() string {
return "goanalysis_metalinter"
}
func (MetaLinter) Desc() string {
return ""
}
func (ml MetaLinter) getLoadMode() LoadMode {
loadMode := LoadModeNone
for _, l := range ml.linters {
if l.loadMode > loadMode {View on GitHub (pinned to ed7a235d2d)
Solutions
- Run `golangci-lint cache clean` and re-run to rule out stale analysis cache
- Read the wrapped cause after 'failed to pre-run <name>:' and fix the underlying linter-specific issue (usually package loading/typecheck errors)
- Disable the offending linter in .golangci.yml to confirm which one fails, then re-enable only after fixing
- Check that all packages compile (`go build ./...`) before linting; preRun often fails on non-compiling code
Example fix
// before (.golangci.yml) - linter fails in pre-run due to bad config
linters:
enable: [govet, staticcheck, custom-linter]
// after - disable/reconfigure the failing linter or fix config
linters:
enable: [govet, staticcheck]
settings:
custom-linter:
path: ./correct-plugin-path.so Defensive patterns
Strategy: try-catch
Validate before calling
// shell check before invoking golangci-lint if ! go build ./...; then echo 'fix compile errors before linting'; fi
Try / catch
// wrap CLI run and inspect wrapped cause
out, err := runGolangciLint()
if err != nil {
var prerunErr *LinterPrerunError // or match on "failed to pre-run"
if strings.Contains(err.Error(), "failed to pre-run ") {
linterName := extractBetween(err.Error(), "failed to pre-run ", ":")
log.Printf("disabling broken linter: %s", linterName)
// retry without that linter
}
return err
} Prevention
- Keep .golangci.yml minimal; enable linters incrementally and verify each
- Ensure `go build ./...` passes before every lint run in CI
- Pin the golangci-lint version and keep linter configs compatible with it
- Run `golangci-lint cache clean` after toolchain upgrades
When it happens
Trigger: Running golangci-lint with a linter whose preRun hook fails — e.g. a linter cannot load packages/types during its setup phase; Run() is invoked with a linter.Context and one of ml.linters returns a non-nil error from preRun(lintCtx).
Common situations: Enabling linters in .golangci.yml that require build tags, GOPATH/module layout or generated code that doesn't resolve; typecheck failures in the analyzed packages surfacing through a linter's setup step; incompatible linter/plugin versions after upgrading golangci-lint.
Related errors
- can't load config: %w
- can't get enabled linters: %w
- failed to read go.mod: %w
- failed to compute go.sum: %w
- can't parse line number %q: %w
AI-assisted analysis of golangci/golangci-lint@ed7a235d2d (2026-09-02).
Data as JSON: /api/errors/edf40bbe78215cea.
Report an issue: GitHub.