golangci/golangci-lint · error

%s: %w

Error message

%s: %w

What it means

In golangci-lint's analysis runner, after the golangci analysis framework executes each action, any action error is attributed to its analyzer: fmt.Errorf("%s: %w", act.Analyzer.Name, act.Err). Panics are re-paniced; otherwise every analyzer failure surfaces in this wrapped form.

Source

Thrown at pkg/goanalysis/runner.go:313

		}
	}

	// De-duplicate diagnostics by position (not token.Pos) to
	// avoid double-reporting in source files that belong to
	// multiple packages, such as foo and foo.test.
	type key struct {
		token.Position
		*analysis.Analyzer
		message string
	}
	seen := make(map[key]bool)

	extract = func(act *action) {
		if act.Err != nil {
			if pe, ok := act.Err.(*errorutil.PanicError); ok {
				panic(pe)
			}
			retErrors = append(retErrors, fmt.Errorf("%s: %w", act.Analyzer.Name, act.Err))
			return
		}

		if act.IsRoot {
			for _, diag := range act.Diagnostics {
				// We don't display a.Name/f.Category
				// as most users don't care.

				position := GetFilePositionFor(act.Package.Fset, diag.Pos)
				file := act.Package.Fset.File(diag.Pos)

				k := key{Position: position, Analyzer: act.Analyzer, message: diag.Message}
				if seen[k] {
					continue // duplicate
				}
				seen[k] = true

				retDiag := &Diagnostic{

View on GitHub (pinned to ed7a235d2d)

Solutions

  1. Fix the root cause named after the analyzer name prefix in the message
  2. Run `go vet ./...` / `go build ./...` first — many analyzer errors stem from packages that don't type-check
  3. Clean the golangci-lint cache (`golangci-lint cache clean`) and re-run
  4. Reproduce with the single analyzer enabled (`golangci-lint run -E <analyzer>`) and report upstream if it's a tool bug

Example fix

// before - running linters over broken package
// go build ./... fails: undefined: Foo
$ golangci-lint run
// after - fix compile errors first, then lint
$ go build ./... && golangci-lint run
Defensive patterns

Strategy: try-catch

Validate before calling

// gate linting behind successful type-check
if err := sh.Run("go", "build", "./..."); err != nil {
    return fmt.Errorf("skip lint: packages must type-check: %w", err)
}

Try / catch

// match analyzer-prefixed errors and isolate the analyzer
out, err := runGolangciLint(args...)
if err != nil && strings.Contains(out, actErrPrefix) {
    analyzer := strings.SplitN(msg, ": ", 2)[0]
    // rerun with -E everything except `analyzer`, or report upstream
}

Prevention

When it happens

Trigger: An analyzer's Analyze method returns an error (e.g. nil pointer on unexpected AST/package shape, type-check info missing) — the runner collects it in retErrors during result extraction.

Common situations: Running analyzers over packages with type errors (missing Facts/TypesInfo), analyzers that assume generated code exists, version mismatches between golangci-lint and Go toolchain producing unexpected package graphs.

Related errors


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