golangci/golangci-lint · error

custom linter %q: %w

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.

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)

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.