golangci/golangci-lint · error
can't start CPU profiling: %w
Error message
can't start CPU profiling: %w
What it means
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.
Source
Thrown at pkg/commands/run.go:271
if exitErr, ok := errors.AsType[*exitcodes.ExitError](err); ok {
c.exitCode = exitErr.Code
} else {
c.exitCode = exitcodes.Failure
}
}
}
c.setupExitCode(ctx)
}
func (c *runCommand) startTracing() error {
if c.opts.CPUProfilePath != "" {
f, err := os.Create(c.opts.CPUProfilePath)
if err != nil {
return fmt.Errorf("can't create file %s: %w", c.opts.CPUProfilePath, err)
}
if err := pprof.StartCPUProfile(f); err != nil {
return fmt.Errorf("can't start CPU profiling: %w", err)
}
}
if c.opts.MemProfilePath != "" {
if rate := os.Getenv(envMemProfileRate); rate != "" {
runtime.MemProfileRate, _ = strconv.Atoi(rate)
}
}
if c.opts.TracePath != "" {
f, err := os.Create(c.opts.TracePath)
if err != nil {
return fmt.Errorf("can't create file %s: %w", c.opts.TracePath, err)
}
if err = trace.Start(f); err != nil {
return fmt.Errorf("can't start tracing: %w", err)
}
}View on GitHub (pinned to ed7a235d2d)
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.
Example fix
// before pprof.StartCPUProfile(f) err := commands.NewRunCommand().Execute() // panics/errors: profile already active // after pprof.StopCPUProfile() err := commands.NewRunCommand().Execute()
Defensive patterns
Strategy: try-catch
Validate before calling
if os.Getenv("GOLANGCI_CPU_PROFILE") != "" { // ensure no profile active in-process
pprof.StopCPUProfile()
} Try / catch
out, err := cmd.Output()
var pprofErr error
if err != nil {
if strings.Contains(err.Error(), "can't start CPU profiling") {
pprofErr = fmt.Errorf("a CPU profile is already active; stop it or drop --cpu-profile: %w", err)
}
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- can't write heap profile: %w
- can't combine option --config and --no-config
- can't load config: %w
- can't get enabled linters: %w
- can't create file %s: %w
AI-assisted analysis of golangci/golangci-lint@ed7a235d2d (2026-09-02).
Data as JSON: /api/errors/dc5130dd2b02d24b.
Report an issue: GitHub.