golangci/golangci-lint · error

writing file %s: %w

Error message

writing file %s: %w

What it means

This error is returned by writeNewFile in the migrate cloner when os.WriteFile fails to persist the formatted cloned configuration file to dstPath. The clone step of `golangci-lint migrate` copies and re-formats the old configuration, and any filesystem-level failure during the write is wrapped with the destination path for context. It indicates the migration aborted because the output file could not be written.

Source

Thrown at pkg/commands/internal/migrate/cloner/cloner.go:191

	err := printer.Fprint(&buf, fset, file)
	if err != nil {
		return fmt.Errorf("printing %s: %w", srcPath, err)
	}

	dstPath := filepath.Join(dstDir, filepath.Base(srcPath))

	_ = os.MkdirAll(filepath.Dir(dstPath), os.ModePerm)

	formatted, err := imports.Process(dstPath, buf.Bytes(), nil)
	if err != nil {
		return fmt.Errorf("formatting %s: %w", dstPath, err)
	}

	//nolint:gosec,mnd // The permission is right.
	err = os.WriteFile(dstPath, formatted, 0o644)
	if err != nil {
		return fmt.Errorf("writing file %s: %w", dstPath, err)
	}

	return nil
}

View on GitHub (pinned to ed7a235d2d)

Solutions

  1. Check that the parent directory of the destination file exists and is writable by the current user.
  2. Free disk space and re-run the migrate command.
  3. If the path is a directory or locked by another process, choose a different output path or close the locking process.
  4. Re-run with elevated permissions only if the target location genuinely requires them.

Example fix

// before
err = os.WriteFile(dstPath, formatted, 0o644)
// after
if err := os.MkdirAll(filepath.Dir(dstPath), 0o755); err != nil {
    return fmt.Errorf("creating dir for %s: %w", dstPath, err)
}
if err := os.WriteFile(dstPath, formatted, 0o644); err != nil {
    return fmt.Errorf("writing file %s: %w", dstPath, err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if err := os.MkdirAll(filepath.Dir(dstPath), 0o755); err != nil { return err }
if fi, err := os.Stat(dstPath); err == nil && fi.IsDir() { return fmt.Errorf("%s is a directory", dstPath) }

Try / catch

if err := writeNewFile(dstPath, srcPath); err != nil {
    var pe *fs.PathError
    if errors.As(err, &pe) && errors.Is(pe.Err, syscall.EACCES) {
        // handle permission problem on dstPath
    }
    return err
}

Prevention

When it happens

Trigger: os.WriteFile(dstPath, formatted, 0o644) returns an error: destination directory does not exist, read-only filesystem, permission denied, disk full, or dstPath is a directory.

Common situations: Running migrate in a read-only checkout, a directory owned by another user, a full disk (especially CI runners), or when the target output path collides with an existing directory.

Understand the failure class

Background: "Permission denied" / "Failed to write" file errors: why a library can't write its files to disk (EACCES, EPERM, ENOSPC) and how to fix them — this error's family across 43 libraries.

Related errors


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