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

  1. Run `golangci-lint cache clean` and re-run to rule out stale analysis cache
  2. Read the wrapped cause after 'failed to pre-run <name>:' and fix the underlying linter-specific issue (usually package loading/typecheck errors)
  3. Disable the offending linter in .golangci.yml to confirm which one fails, then re-enable only after fixing
  4. 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

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


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