golangci/golangci-lint · error

can't read viper config: %w

Error message

can't read viper config: %w

What it means

parseConfig calls viper.ReadInConfig; if reading fails for reasons other than "config file not found" (parse errors, permission, IO), the error is wrapped as "can't read viper config" and config loading stops.

Source

Thrown at pkg/config/base_loader.go:168

		searchPaths = append(searchPaths, home)
	}

	return searchPaths
}

func (l *BaseLoader) parseConfig() error {
	if err := l.viper.ReadInConfig(); err != nil {
		if _, ok := errors.AsType[viper.ConfigFileNotFoundError](err); ok {
			// Load configuration from flags only.
			err = l.viper.Unmarshal(l.cfg, customDecoderHook())
			if err != nil {
				return fmt.Errorf("can't unmarshal config by viper (flags): %w", err)
			}

			return nil
		}

		return fmt.Errorf("can't read viper config: %w", err)
	}

	err := l.setConfigDir()
	if err != nil {
		return err
	}

	// Load configuration from all sources (flags, file).
	if err := l.viper.Unmarshal(l.cfg, customDecoderHook()); err != nil {
		return fmt.Errorf("can't unmarshal config by viper (flags, file): %w", err)
	}

	if l.cfg.IsInternalTest() { // just for testing purposes: to detect config file usage
		_, _ = fmt.Fprintln(logutils.StdOut, "test")
		os.Exit(exitcodes.Success)
	}

	return nil

View on GitHub (pinned to ed7a235d2d)

Solutions

  1. Validate the YAML/JSON config file syntax (yamllint or a YAML parser) and fix syntax errors
  2. Check file permissions so the lint process can read the config file
  3. Use `golangci-lint config path` to see which config file is being picked up; remove or fix stale ones
  4. Read the wrapped %w error — viper reports the file and line of parse failures

Example fix

# before (invalid YAML)
issues:
	exclude-dirs:
  - vendor
# after
issues:
  exclude-dirs:
    - vendor
Defensive patterns

Strategy: validation

Validate before calling

func validYAML(path string) error {
	data, err := os.ReadFile(path)
	if err != nil {
		return err
	}
	var v map[string]any
	return yaml.Unmarshal(data, &v)
}
// run in CI before golangci-lint: validYAML(".golangci.yml")

Prevention

When it happens

Trigger: A config file exists at the resolved location but viper cannot read/parse it: malformed YAML/JSON/TOML syntax, unreadable file permissions, unreadable config directory (setConfigDir side effects happen after), or a corrupted search path.

Common situations: Hand-edited .golangci.yml with indentation/tab mistakes; merge-conflict markers left in the file; root-owned config in CI containers; a stray .golangci.yaml in a parent directory with bad syntax.

Related errors


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