{"record":{"id":"bf0dc4d7026b56a8","repo":"golangci/golangci-lint","slug":"s-w-bf0dc4","errorCode":null,"errorMessage":"%s: %w","messagePattern":"%s: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/lint/runner.go","lineNumber":162,"sourceCode":"\t\t\tlintErrors = errors.Join(lintErrors, fmt.Errorf(\"can't run linter %s\", lc.Linter.Name()), err)\n\t\t\tr.Log.Warnf(\"Can't run linter %s: %v\", lc.Linter.Name(), err)\n\n\t\t\tcontinue\n\t\t}\n\n\t\tissues = append(issues, linterIssues...)\n\t}\n\n\treturn r.processLintResults(issues), lintErrors\n}\n\nfunc (r *Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context,\n\tlc *linter.Config,\n) (ret []*result.Issue, err error) {\n\tdefer func() {\n\t\tif panicData := recover(); panicData != nil {\n\t\t\tif pe, ok := panicData.(*errorutil.PanicError); ok {\n\t\t\t\terr = fmt.Errorf(\"%s: %w\", lc.Name(), pe)\n\n\t\t\t\t// Don't print stacktrace from goroutines twice\n\t\t\t\tr.Log.Errorf(\"Panic: %s: %s\", pe, pe.Stack())\n\t\t\t} else {\n\t\t\t\terr = fmt.Errorf(\"panic occurred: %s\", panicData)\n\t\t\t\tr.Log.Errorf(\"Panic stack trace: %s\", debug.Stack())\n\t\t\t}\n\t\t}\n\t}()\n\n\tissues, err := lc.Linter.Run(ctx, lintCtx)\n\n\tif lc.DoesChangeTypes {\n\t\t// Packages in lintCtx might be dirty due to the last analysis,\n\t\t// which affects to the next analysis.\n\t\t// To avoid this issue, we clear type information from the packages.\n\t\t// See https://github.com/golangci/golangci-lint/pull/944.\n\t\t// Currently, DoesChangeTypes is true only for `unused`.","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/golangci/golangci-lint/blob/ed7a235d2d771152056fdc142a9855567c5796a9/pkg/lint/runner.go#L144-L180","documentation":"runLinterSafe wraps linter execution in a recover() defer. If a linter panics with an *errorutil.PanicError, it is converted to \"<lintername>: <panic error>\" and logged with its stack trace; other panic values become a generic \"panic occurred\" error. This prevents one linter's crash from aborting the whole golangci-lint run.","triggerScenarios":"A bug inside a linter (index out of range, nil dereference) triggered while analyzing specific code patterns, concurrent map access, or a linter analysis pass hitting an unexpected AST/type state. The panic is recovered in runLinterSafe and surfaced as this wrapped error.","commonSituations":"Linter bugs on unusual code (generics edge cases, exotic build tags); incompatible linter plugin versions; known upstream bugs in a linter release that are fixed in a later version.","solutions":["Identify the linter from the message prefix and check its issue tracker for known panics on your code","Upgrade golangci-lint (and bundled linters) to the latest patch release where the panic may be fixed","Exclude the triggering file/pattern via `linters.exclusions.rules` or `linters.exclusions.paths` as a workaround","Reduce to a minimal reproducing file and report the panic upstream with the logged stack trace"],"exampleFix":"// before (.golangci.yml)\nlinters:\n  enable:\n    - buggedlinter   # panics on generated code\n// after\nlinters:\n  enable:\n    - buggedlinter\n  exclusions:\n    rules:\n      - path: '.*_gen\\.go'\n        linters:\n          - buggedlinter","handlingStrategy":"fallback","validationCode":"// Pre-flight: run the linter standalone on a small sample to detect panicking versions:\n// golangci-lint run --enable-only <name> ./... || echo \"linter panics; pin or exclude\"","typeGuard":null,"tryCatchPattern":"defer func() {\n    if p := recover(); p != nil {\n        if pe, ok := p.(*errorutil.PanicError); ok {\n            err = fmt.Errorf(\"%s: %w\", lc.Name(), pe)\n        } else {\n            err = fmt.Errorf(\"panic occurred: %s\", p)\n        }\n    }\n}()","preventionTips":["Pin golangci-lint to a stable release and upgrade promptly for linter panic fixes","Check linter issue trackers for panics before enabling pre-release linters","Exclude known-trigger files (generated code, exotic generics) via exclusion rules","Always capture and report the logged stack trace when filing upstream bugs"],"tags":["golangci-lint","panic-recovery","linter-runtime"],"backgroundTag":"linter-panic","analyzedSha":"ed7a235d2d771152056fdc142a9855567c5796a9","analyzedAt":"2026-09-02T18:47:33.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}