golangci/golangci-lint · error

failed to get goenv: %w

Error message

failed to get goenv: %w

What it means

computeGoModSalt reads the GOMOD environment value via the goenv package to hash go.mod for cache keys; a goenv.Get failure is wrapped as "failed to get goenv". goenv shells out to / inspects the local Go toolchain, so this indicates the Go environment could not be interrogated.

Source

Thrown at pkg/commands/run.go:706

		return nil, fmt.Errorf("failed to JSON marshal config linter settings: %w", err)
	}

	configData := bytes.NewBufferString("linters.settings=")
	configData.Write(lintersSettingsBytes)
	configData.WriteString("\nbuild-tags=%s" + strings.Join(cfg.Run.BuildTags, ","))

	h := sha256.New()
	if _, err := h.Write(configData.Bytes()); err != nil {
		return nil, err
	}

	return h.Sum(nil), nil
}

func computeGoModSalt() (string, error) {
	values, err := goenv.Get(context.Background(), goenv.GOMOD)
	if err != nil {
		return "", fmt.Errorf("failed to get goenv: %w", err)
	}

	goModPath := filepath.Clean(values[goenv.GOMOD])

	data, err := os.ReadFile(goModPath)
	if err != nil {
		return "", fmt.Errorf("failed to read go.mod: %w", err)
	}

	// NOTE: the variable `goModPath` is not used here to ensure getting the same hash, independently of the location, for the same content.
	sum, err := dirhash.Hash1([]string{"go.mod"}, func(string) (io.ReadCloser, error) {
		return io.NopCloser(bytes.NewReader(data)), nil
	})
	if err != nil {
		return "", fmt.Errorf("failed to compute go.sum: %w", err)
	}

	return sum, nil

View on GitHub (pinned to ed7a235d2d)

Solutions

  1. Ensure the `go` toolchain is installed and on PATH (`which go`, `go version`).
  2. Run from within a Go module directory; the code only warns on missing go.mod, but goenv itself must still succeed.
  3. In minimal Docker images, keep the go binary or run the lint stage in a full Go image (e.g. golang:1.x).
  4. Fix corrupted Go installations (reinstall the toolchain) if `go env` itself errors.
  5. Check inherited GOFLAGS/GO111MODULE values that could make `go env` fail.

Example fix

// before (Dockerfile)
FROM alpine
COPY golangci-lint /usr/bin/   # no go toolchain -> goenv fails
// after
FROM golang:1.22
COPY golangci-lint /usr/bin/
Defensive patterns

Strategy: validation

Validate before calling

if _, err := exec.LookPath("go"); err != nil {
	return fmt.Errorf("go toolchain not on PATH; goenv (and cache salt) will fail")
}
if err := exec.Command("go", "version").Run(); err != nil {
	return fmt.Errorf("go binary present but broken: %w", err)
}

Try / catch

if err := cmd.Run(); err != nil && strings.Contains(err.Error(), "failed to get goenv") {
	log.Fatalf("ensure `go` is installed and on PATH: %v", err)
}

Prevention

When it happens

Trigger: goenv.Get(context.Background(), goenv.GOMOD) fails — typically the `go` binary is missing from PATH, or running `go env GOMOD` errors (broken Go installation, GOFLAGS/env problems, go unavailable in the sandbox).

Common situations: CI images without the Go toolchain installed (only the golangci-lint binary); restricted Docker images where the go binary was removed to shrink size; PATH not including /usr/local/go/bin in cron or systemd contexts.

Related errors


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