{"record":{"id":"ce13bf7cd3821cf4","repo":"golangci/golangci-lint","slug":"failed-to-json-marshal-config-linter-settings-w","errorCode":null,"errorMessage":"failed to JSON marshal config linter settings: %w","messagePattern":"failed to JSON marshal config linter settings: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/commands/run.go","lineNumber":688,"sourceCode":"\n\tdefer f.Close()\n\n\th := sha256.New()\n\tif _, err := io.Copy(h, f); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn h.Sum(nil), nil\n}\n\n// computeConfigSalt computes configuration hash.\n// We don't hash all config fields to reduce meaningless cache invalidations.\n// At least, it has a huge impact on tests speed.\n// Fields: `LintersSettings` and `Run.BuildTags`.\nfunc computeConfigSalt(cfg *config.Config) ([]byte, error) {\n\tlintersSettingsBytes, err := yaml.Marshal(cfg.Linters.Settings)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to JSON marshal config linter settings: %w\", err)\n\t}\n\n\tconfigData := bytes.NewBufferString(\"linters.settings=\")\n\tconfigData.Write(lintersSettingsBytes)\n\tconfigData.WriteString(\"\\nbuild-tags=%s\" + strings.Join(cfg.Run.BuildTags, \",\"))\n\n\th := sha256.New()\n\tif _, err := h.Write(configData.Bytes()); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn h.Sum(nil), nil\n}\n\nfunc computeGoModSalt() (string, error) {\n\tvalues, err := goenv.Get(context.Background(), goenv.GOMOD)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to get goenv: %w\", err)","sourceCodeStart":670,"sourceCodeEnd":706,"githubUrl":"https://github.com/golangci/golangci-lint/blob/ed7a235d2d771152056fdc142a9855567c5796a9/pkg/commands/run.go#L670-L706","documentation":"Inside computeConfigSalt, golangci-lint marshals cfg.Linters.Settings with yaml.Marshal; failure is wrapped (with a now-inaccurate \"JSON marshal\" message) as \"failed to JSON marshal config linter settings\". This error is propagated up as error 117's cause.","triggerScenarios":"yaml.Marshal returns an error for the linter settings — practically only when the settings struct contains values the marshaller cannot represent, e.g. after programmatic mutation of the config in custom code or unsupported types injected by plugins.","commonSituations":"Forked/patched golangci-lint builds or custom formatters mutating Linters.Settings with non-serializable values; ABI/plugin mismatches where a custom linter writes incompatible data into settings.","solutions":["Find what mutates cfg.Linters.Settings (plugins, custom builds, wrappers) and ensure only standard config types are stored there.","Use an unmodified golangci-lint release binary to rule out patched-build issues.","Simplify .golangci.yml linter settings and re-run to confirm stock configs marshal fine.","Upgrade golangci-lint; the misleading 'JSON' wording was fixed in later versions."],"exampleFix":"// before (custom code)\ncfg.Linters.Settings.Custom[\"x\"] = someOpaqueValue\n// after\ncfg.Linters.Settings.Custom[\"x\"] = config.CustomLinterSettings{Path: \"./x.so\"}","handlingStrategy":"try-catch","validationCode":"// stock binary + stock config should always marshal\nif _, err := yaml.Marshal(lintersSettingsStruct); err != nil {\n\treturn fmt.Errorf(\"settings not serializable; custom mutation detected: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := cmd.Run(); err != nil && strings.Contains(err.Error(), \"failed to JSON marshal config linter settings\") {\n\tlog.Fatalf(\"non-serializable value injected into Linters.Settings (plugin/custom build?): %v\", err)\n}","preventionTips":["Use official golangci-lint release binaries.","Never mutate cfg.Linters.Settings programmatically with non-standard types.","Test custom plugins against the exact golangci-lint version."],"tags":["config","serialization","yaml","cache","golangci-lint"],"backgroundTag":"config-salt-computation-failed","analyzedSha":"ed7a235d2d771152056fdc142a9855567c5796a9","analyzedAt":"2026-09-02T18:47:33.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}