{"record":{"id":"91354e4bffee1e04","repo":"golangci/golangci-lint","slug":"field-module-is-required","errorCode":null,"errorMessage":"field 'module' is required","messagePattern":"field 'module' is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/commands/internal/configuration.go","lineNumber":48,"sourceCode":"}\n\n// Validate checks and clean the configuration.\nfunc (c *Configuration) Validate() error {\n\tif strings.TrimSpace(c.Version) == \"\" {\n\t\treturn errors.New(\"root field 'version' is required\")\n\t}\n\n\tif strings.TrimSpace(c.Name) == \"\" {\n\t\tc.Name = defaultBinaryName\n\t}\n\n\tif len(c.Plugins) == 0 {\n\t\treturn errors.New(\"no plugins defined\")\n\t}\n\n\tfor _, plugin := range c.Plugins {\n\t\tif strings.TrimSpace(plugin.Module) == \"\" {\n\t\t\treturn errors.New(\"field 'module' is required\")\n\t\t}\n\n\t\tif strings.TrimSpace(plugin.Import) == \"\" {\n\t\t\tplugin.Import = plugin.Module\n\t\t}\n\n\t\tif strings.TrimSpace(plugin.Path) == \"\" && strings.TrimSpace(plugin.Version) == \"\" {\n\t\t\treturn errors.New(\"missing information: 'version' or 'path' should be provided\")\n\t\t}\n\n\t\tif strings.TrimSpace(plugin.Path) != \"\" && strings.TrimSpace(plugin.Version) != \"\" {\n\t\t\treturn errors.New(\"invalid configuration: 'version' and 'path' should not be provided at the same time\")\n\t\t}\n\n\t\tif strings.TrimSpace(plugin.Path) == \"\" {\n\t\t\tcontinue\n\t\t}\n","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/golangci/golangci-lint/blob/ed7a235d2d771152056fdc142a9855567c5796a9/pkg/commands/internal/configuration.go#L30-L66","documentation":"Inside the per-plugin loop of `Configuration.Validate` (pkg/commands/internal/configuration.go:48), every plugin entry must have a non-blank `module` field — the Go module path of the plugin (e.g. `github.com/user/golangci-plugin`). This is the first per-plugin check, so a plugin entry with an empty `module` aborts validation before any other field is examined.","triggerScenarios":"A `plugins:` entry in `.custom-gcl.yml` missing the `module:` key, having `module: \"\"`, whitespace only, or the value placed under a misspelled key (e.g. `name:` or `modul:`) so it decodes as empty.","commonSituations":"Hand-writing a new plugin entry and forgetting the module path; copying a local-path plugin example that used `path` only and dropping the module line; YAML list items mis-indented so fields attach to the wrong entry.","solutions":["Add the `module` field with the plugin's Go module import path to the offending plugins entry","Confirm each list item's indentation — every field of one plugin must be under the same `- ` item","Check the plugin's README for its exact module path (module path and import can differ; import defaults to module if omitted)"],"exampleFix":"# before\nplugins:\n  - version: v1.0.0\n# after\nplugins:\n  - module: github.com/me/my-plugin\n    version: v1.0.0","handlingStrategy":"validation","validationCode":"var raw struct {\n\tPlugins []struct {\n\t\tModule string `yaml:\"module\"`\n\t} `yaml:\"plugins\"`\n}\n_ = yaml.Unmarshal(data, &raw)\nfor i, p := range raw.Plugins {\n\tif strings.TrimSpace(p.Module) == \"\" {\n\t\tlog.Fatalf(\"plugins[%d]: missing module\", i)\n\t}\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Copy the plugin's documented `module:` line verbatim from its README","Verify list-item indentation so fields belong to the intended plugin entry","Remember `import` is optional and defaults to `module`; `module` itself is mandatory"],"tags":["custom-gcl","config","plugin","validation"],"backgroundTag":"missing-required-config-field","analyzedSha":"ed7a235d2d771152056fdc142a9855567c5796a9","analyzedAt":"2026-09-02T18:47:33.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}