{"record":{"id":"dc5130dd2b02d24b","repo":"golangci/golangci-lint","slug":"can-t-start-cpu-profiling-w","errorCode":null,"errorMessage":"can't start CPU profiling: %w","messagePattern":"can't start CPU profiling: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/commands/run.go","lineNumber":271,"sourceCode":"\t\t\tif exitErr, ok := errors.AsType[*exitcodes.ExitError](err); ok {\n\t\t\t\tc.exitCode = exitErr.Code\n\t\t\t} else {\n\t\t\t\tc.exitCode = exitcodes.Failure\n\t\t\t}\n\t\t}\n\t}\n\n\tc.setupExitCode(ctx)\n}\n\nfunc (c *runCommand) startTracing() error {\n\tif c.opts.CPUProfilePath != \"\" {\n\t\tf, err := os.Create(c.opts.CPUProfilePath)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"can't create file %s: %w\", c.opts.CPUProfilePath, err)\n\t\t}\n\t\tif err := pprof.StartCPUProfile(f); err != nil {\n\t\t\treturn fmt.Errorf(\"can't start CPU profiling: %w\", err)\n\t\t}\n\t}\n\n\tif c.opts.MemProfilePath != \"\" {\n\t\tif rate := os.Getenv(envMemProfileRate); rate != \"\" {\n\t\t\truntime.MemProfileRate, _ = strconv.Atoi(rate)\n\t\t}\n\t}\n\n\tif c.opts.TracePath != \"\" {\n\t\tf, err := os.Create(c.opts.TracePath)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"can't create file %s: %w\", c.opts.TracePath, err)\n\t\t}\n\t\tif err = trace.Start(f); err != nil {\n\t\t\treturn fmt.Errorf(\"can't start tracing: %w\", err)\n\t\t}\n\t}","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/golangci/golangci-lint/blob/ed7a235d2d771152056fdc142a9855567c5796a9/pkg/commands/run.go#L253-L289","documentation":"golangci-lint wraps the error returned by runtime/pprof's StartCPUProfile when the user requested CPU profiling via --cpu-profile. StartCPUProfile fails only if a CPU profile is already active in the process. The wrap preserves the underlying pprof error so the CLI can exit with a clear message.","triggerScenarios":"Running golangci-lint with --cpu-profile set while another CPU profile was already started in the same process (pprof allows only one active CPU profile).","commonSituations":"Test harnesses or wrapper scripts that start profiling themselves and then invoke the profiling-enabled lint run in-process; double invocation of persistentPreRunE in custom command compositions.","solutions":["Remove the pre-existing pprof.StartCPUProfile call (or stop it with pprof.StopCPUProfile) before running golangci-lint with --cpu-profile.","Run golangci-lint as a separate process instead of embedding it in a program that already profiles itself.","Drop --cpu-profile if profiling is not needed; use a different output path only when the conflict is with another run's profile file."],"exampleFix":"// before\npprof.StartCPUProfile(f)\nerr := commands.NewRunCommand().Execute() // panics/errors: profile already active\n// after\npprof.StopCPUProfile()\nerr := commands.NewRunCommand().Execute()","handlingStrategy":"try-catch","validationCode":"if os.Getenv(\"GOLANGCI_CPU_PROFILE\") != \"\" { // ensure no profile active in-process\n\tpprof.StopCPUProfile()\n}","typeGuard":null,"tryCatchPattern":"out, err := cmd.Output()\nvar pprofErr error\nif err != nil {\n\tif strings.Contains(err.Error(), \"can't start CPU profiling\") {\n\t\tpprofErr = fmt.Errorf(\"a CPU profile is already active; stop it or drop --cpu-profile: %w\", err)\n\t}\n}","preventionTips":["Never start pprof.StartCPUProfile in the host program when delegating to golangci-lint with --cpu-profile.","Profile the wrapper and the linter in separate processes.","Pair every StartCPUProfile with a StopCPUProfile in defer."],"tags":["profiling","pprof","cli","golangci-lint"],"backgroundTag":"cpu-profile-already-active","analyzedSha":"ed7a235d2d771152056fdc142a9855567c5796a9","analyzedAt":"2026-09-02T18:47:33.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}