golangci/golangci-lint · error

invalid check settings: check %q doesn't exist, see %s docum

Error message

invalid check settings: check %q doesn't exist, see %s documentation

What it means

gocritic per-check settings (settings.gocritic.settings.<check>) must reference an existing gocritic check, compared case-insensitively. A settings key that doesn't match any check (lowercased) aborts the run with this error.

Source

Thrown at pkg/golinters/gocritic/gocritic_settings.go:363

func (s *settingsWrapper) validateCheckerNames() error {
	for _, check := range s.EnabledChecks {
		if !s.allChecks.has(check) {
			return fmt.Errorf("enabled check %q doesn't exist, see %s's documentation", check, linterName)
		}
	}

	for _, check := range s.DisabledChecks {
		if !s.allChecks.has(check) {
			return fmt.Errorf("disabled check %q doesn't exist, see %s documentation", check, linterName)
		}
	}

	for check := range s.SettingsPerCheck {
		lcName := strings.ToLower(check)

		if !s.allChecksLowerCased.has(lcName) {
			return fmt.Errorf("invalid check settings: check %q doesn't exist, see %s documentation", check, linterName)
		}

		if !s.inferredEnabledChecksLowerCased.has(lcName) {
			s.logger.Warnf("%s: settings were provided for disabled check %q", check, linterName)
		}
	}

	return nil
}

func (s *settingsWrapper) validateDisabledAndEnabledAtOneMoment() error {
	for _, tag := range s.DisabledTags {
		if slices.Contains(s.EnabledTags, tag) {
			return fmt.Errorf("tag %q disabled and enabled at one moment", tag)
		}
	}

	for _, check := range s.DisabledChecks {

View on GitHub (pinned to ed7a235d2d)

Solutions

  1. Fix the check-name key under settings.gocritic.settings to match a real gocritic check (case-insensitive)
  2. Remove the settings block for the nonexistent check
  3. Confirm the check exists in your pinned gocritic version
  4. Optionally add the (valid) check to enabled-checks; note a separate warning fires if settings target a disabled check

Example fix

// before (.golangci.yml)
settings:
  gocritic:
    settings:
      rangValCopy:
        rangeSizeThreshold: 128
// after
settings:
  gocritic:
    settings:
      rangeValCopy:
        rangeSizeThreshold: 128
Defensive patterns

Strategy: validation

Validate before calling

const knownLower = new Set(getGocriticChecksForVersion().map(c => c.toLowerCase()))
const bad = Object.keys(cfg.settings.gocritic.settings ?? {}).filter(k => !knownLower.has(k.toLowerCase()))
if (bad.length) throw new Error(`settings for unknown gocritic checks: ${bad.join(', ')}`)

Type guard

const hasValidCheckSettings = (s) => Object.keys(s ?? {}).every(k => knownLower.has(k.toLowerCase()))

Prevention

When it happens

Trigger: validateCheckerNames iterates s.SettingsPerCheck, lowercases each key, and fails when allChecksLowerCased doesn't contain it — e.g. key 'RangeValCopy ' with typo or a check name from another linter.

Common situations: Typos in per-check setting keys, providing settings for a check removed in a gocritical upgrade, pasting settings blocks from example configs for checks that don't exist.

Related errors


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