golangci/golangci-lint · error

can't create file %s: %w

Error message

can't create file %s: %w

What it means

When CPU profiling is requested (--cpu-profile-path), `startTracing` creates the profile file with os.Create. If the file cannot be created, the error is wrapped as `can't create file %s: %w`. The path and underlying OS error are both included, so the cause is directly actionable.

Source

Thrown at pkg/commands/run.go:268

	if err := c.runAndPrint(ctx); err != nil {
		c.log.Errorf("Running error: %s", err)
		if c.exitCode == exitcodes.Success {
			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 {

View on GitHub (pinned to ed7a235d2d)

Solutions

  1. Create the parent directory of the profile path before running (mkdir -p).
  2. Point --cpu-profile-path at a writable location (e.g. /tmp/cpu.prof).
  3. Fix permissions on the target directory (chmod/chown) or run as a user with write access.
  4. Check the wrapped OS error after the message — 'no such file or directory' vs 'permission denied' vs 'is a directory' point to different fixes.
  5. Free disk space if the error indicates the filesystem is full.

Example fix

// before
- run: golangci-lint run --cpu-profile-path=profiles/cpu.prof  # profiles/ missing
// after
- run: |
    mkdir -p profiles
    golangci-lint run --cpu-profile-path=profiles/cpu.prof
Defensive patterns

Strategy: validation

Validate before calling

// verify the profile path's directory is writable before enabling profiling
profDir := filepath.Dir(cpuProfilePath)
if err := os.MkdirAll(profDir, 0o755); err != nil {
    return fmt.Errorf("cannot create profile dir %s: %w", profDir, err)
}

Try / catch

f, err := os.Create(c.opts.CPUProfilePath)
if err != nil {
    var pe *fs.PathError
    if errors.As(err, &pe) {
        log.Printf("create failed: path=%s op=%s err=%v", pe.Path, pe.Op, pe.Err)
    }
    return fmt.Errorf("can't create file %s: %w", c.opts.CPUProfilePath, err)
}

Prevention

When it happens

Trigger: Passing --cpu-profile-path pointing to a non-existent directory, a path without write permission, or a path that is itself a directory; also disk-full or read-only filesystem conditions during os.Create.

Common situations: CI passing a profile path under a directory that was never created; typos in the path; running in a read-only container filesystem; permission mismatch when running the linter as a different user.

Related errors


AI-assisted analysis of golangci/golangci-lint@ed7a235d2d (2026-09-02). Data as JSON: /api/errors/3ce64016ae28be34. Report an issue: GitHub.