golangci/golangci-lint · error

custom linter

Error message

custom linter %q: %w

What it means

During LintersSettings validation, each entry in settings.custom is validated; a failure is wrapped as 'custom linter %q: %w' with the plugin's name. This means a user-defined (plugin) linter's settings block — typically its path and type — is invalid.

Solutions

  1. Read the wrapped inner error for the exact field problem on the named custom linter
  2. Set the required keys (path and type) in linters.settings.custom.<name>
  3. Rebuild the plugin .so with the matching golangci-lint version and fix the path

Example fix

# before
linters:
  settings:
    custom:
      mylinter:
        type: module
# after
linters:
  settings:
    custom:
      mylinter:
        path: ./plugin/mylinter.so
        type: plugin
Defensive patterns

Strategy: validation

Validate before calling

for name, s := range cfg.Linters.Settings.Custom {
	if s.Path == "" {
		return fmt.Errorf("custom linter %q: path is required", name)
	}
	if _, err := os.Stat(s.Path); err != nil {
		return fmt.Errorf("custom linter %q: plugin not found: %w", name, err)
	}
}

Try / catch

if err := settings.Validate(); err != nil {
	log.Fatalf("custom linter config: %v", err)
}

Prevention

When it happens

Trigger: Config linters.settings.custom.<name> missing required fields (e.g. no 'path' to the plugin .so, bad 'type'), or the referenced plugin file failing the inner validation.

Common situations: Custom plugin path typo or .so not built; using module plugin type without a valid module path; upgrading plugins after golangci-lint version change.

Related errors


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

Appendix: source

Thrown at pkg/config/linters_settings.go:355

	UseStdlibVars            UseStdlibVarsSettings            `mapstructure:"usestdlibvars"`
	UseTesting               UseTestingSettings               `mapstructure:"usetesting"`
	Varnamelen               VarnamelenSettings               `mapstructure:"varnamelen"`
	Whitespace               WhitespaceSettings               `mapstructure:"whitespace"`
	Wrapcheck                WrapcheckSettings                `mapstructure:"wrapcheck"`
	WSL                      WSLv4Settings                    `mapstructure:"wsl"` // Deprecated: use WSLv5 instead.
	WSLv5                    WSLv5Settings                    `mapstructure:"wsl_v5"`

	Custom map[string]CustomLinterSettings `mapstructure:"custom"`
}

func (s *LintersSettings) Validate() error {
	if err := s.Govet.Validate(); err != nil {
		return err
	}

	for name, settings := range s.Custom {
		if err := settings.Validate(); err != nil {
			return fmt.Errorf("custom linter %q: %w", name, err)
		}
	}

	return nil
}

type AsasalintSettings struct {
	Exclude              []string `mapstructure:"exclude"`
	UseBuiltinExclusions bool     `mapstructure:"use-builtin-exclusions"`
}

type BiDiChkSettings struct {
	LeftToRightEmbedding     bool `mapstructure:"left-to-right-embedding"`
	RightToLeftEmbedding     bool `mapstructure:"right-to-left-embedding"`
	PopDirectionalFormatting bool `mapstructure:"pop-directional-formatting"`
	LeftToRightOverride      bool `mapstructure:"left-to-right-override"`
	RightToLeftOverride      bool `mapstructure:"right-to-left-override"`
	LeftToRightIsolate       bool `mapstructure:"left-to-right-isolate"`

View on GitHub (pinned to ed7a235d2d)