golangci/golangci-lint · error

%w

Error message

%w

What it means

Env.Discover reads GOCACHE and GOROOT by invoking the go toolchain via goenv.Get (grignotin/goenv). This error is returned when that call fails: the go binary could not be executed, its output could not be parsed, or the context was canceled. The raw error is re-wrapped verbatim with fmt.Errorf("%w", err), so the root cause appears directly in the message.

Source

Thrown at pkg/goutil/env.go:34

type Env struct {
	vars map[string]string
	log  logutils.Log
}

func NewEnv(log logutils.Log) *Env {
	return &Env{
		vars: map[string]string{},
		log:  log,
	}
}

func (e Env) Discover(ctx context.Context) error {
	startedAt := time.Now()

	var err error
	e.vars, err = goenv.Get(ctx, goenv.GOCACHE, goenv.GOROOT)
	if err != nil {
		return fmt.Errorf("%w", err)
	}

	e.log.Infof("Read go env for %s: %#v", time.Since(startedAt), e.vars)

	return nil
}

func (e Env) Get(k EnvKey) string {
	envValue := os.Getenv(string(k))
	if envValue != "" {
		return envValue
	}

	return e.vars[string(k)]
}

View on GitHub (pinned to ed7a235d2d)

Solutions

  1. Verify `go env GOCACHE GOROOT` succeeds in the same shell/environment where golangci-lint runs.
  2. Install the Go toolchain and ensure it is on PATH inside the container/CI job running the linter.
  3. Check GOENV, GOFLAGS, GOPROXY and GOCACHE environment variables for invalid or conflicting values.
  4. Run with verbose logging to surface the wrapped root cause if the message is opaque.
  5. As a last resort, reinstall a supported Go version and clear GOCACHE (`go clean -cache`).

Example fix

# before (CI image without a toolchain)
image: golangci/golangci-lint:latest  # no go installed, `go env` fails
# after
image: golang:1.23
script:
  - go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest
  - golangci-lint run
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure the go toolchain is usable before invoking the linter
func checkGoToolchain() error {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	if out, err := exec.CommandContext(ctx, "go", "env", "GOCACHE", "GOROOT").Output(); err != nil {
		return fmt.Errorf("go toolchain unavailable: %w", err)
	} else {
		_ = out
	}
	return nil
}

Try / catch

env := goutil.NewEnv(log)
if err := env.Discover(ctx); err != nil {
	if errors.Is(err, context.DeadlineExceeded) {
		return fmt.Errorf("go env timed out; check GOFLAGS/proxy settings: %w", err)
	}
	return fmt.Errorf("cannot read go env (is Go installed and on PATH?): %w", err)
}

Prevention

When it happens

Trigger: Calling Discover (directly or via runAndPrint during a golangci-lint run) when the go binary is missing from PATH, the Go version is too old or its `go env` output format is unexpected, GOCACHE/GOROOT point to invalid locations, `go env` exits non-zero, or ctx is canceled before goenv.Get completes.

Common situations: Running golangci-lint in a Docker/CI image without the Go toolchain; GOENV/GOFLAGS misconfiguration breaking `go env`; GOCACHE pointing to a non-writable path; a broken Go installation after an upgrade.

Related errors


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