golangci/golangci-lint · error

failed prerequisites: %w

Error message

failed prerequisites: %w

What it means

The go-analysis runner checks each action's dependencies before running it. If any dependency action finished with an error, those errors are joined (errors.Join of unwrapped dep errors) and stored as the current action's error prefixed with 'failed prerequisites:'. The action itself never executes.

Source

Thrown at pkg/goanalysis/runner_checker.go:98

	// In parallel mode, due to GC/scheduler contention, the
	// time is 5x higher than in sequential mode, even with a
	// semaphore limiting the number of threads here.
	// So use -debug=tp.
	t0 := time.Now()
	defer func() {
		act.Duration = time.Since(t0)
		analyzeDebugf("go/analysis: %s: %s: analyzed package %q in %s", act.runner.prefix, act.Analyzer.Name, act.Package.Name, time.Since(t0))
	}()

	// Report an error if any dependency failures.
	var depErrors error
	for _, dep := range act.Deps {
		if dep.Err != nil {
			depErrors = errors.Join(depErrors, errors.Unwrap(dep.Err))
		}
	}
	if depErrors != nil {
		act.Err = fmt.Errorf("failed prerequisites: %w", depErrors)
		return
	}

	// Plumb the output values of the dependencies
	// into the inputs of this action.  Also facts.
	inputs := make(map[*analysis.Analyzer]any)
	act.objectFacts = make(map[objectFactKey]analysis.Fact)
	act.packageFacts = make(map[packageFactKey]analysis.Fact)
	for _, dep := range act.Deps {
		if dep.Package == act.Package {
			// Same package, different analysis (horizontal edge):
			// in-memory outputs of prerequisite analyzers
			// become inputs to this analysis pass.
			inputs[dep.Analyzer] = dep.Result

		} else if dep.Analyzer == act.Analyzer { // (always true)
			// Same analysis, different package (vertical edge):
			// serialized facts produced by prerequisite analysis

View on GitHub (pinned to ed7a235d2d)

Solutions

  1. Look below the 'failed prerequisites:' prefix — the joined dependency errors name the real root cause; fix that first
  2. Ensure the analyzed packages type-check (`go build ./...`) before linting
  3. Run with fewer analyzers to isolate which dependency chain fails
  4. Clean the analysis cache and retry to rule out a corrupted action cache

Example fix

// before - analyzing packages with type errors
// pkg/a.go: undefined: Missing
$ golangci-lint run ./...
// failed prerequisites: ... (cascade)
// after - fix the dependency error first
$ go build ./... # fix pkg/a.go
$ golangci-lint run ./...
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure all deps type-check before running dependent analyzers
if err := sh.Run("go", "build", "./..."); err != nil {
    return err // prevents cascading 'failed prerequisites'
}

Try / catch

// when using the analysis framework directly
if err := pass.Run(...); err != nil {
    if strings.HasPrefix(err.Error(), "failed prerequisites:") {
        cause := errors.Unwrap(err) // joined dep errors; log and fix root
    }
    return err
}

Prevention

When it happens

Trigger: Analyzer A depends on analyzer B's facts/results; B's action errored (e.g. B panicked or returned an error), so every dependent action A is marked failed with this message.

Common situations: Cascading failures after one root analyzer error (see runner.go extraction); packages that fail type-checking so fact-producing analyzers (buildtag, stdmethods, etc.) error first; mixed analyzer versions where a required fact is never produced.

Related errors


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