golangci/golangci-lint · error

create temporary directory: %w

Error message

create temporary directory: %w

What it means

customCommand.runE builds a custom golangci-lint binary and first creates a temporary working directory with os.MkdirTemp(os.TempDir(), "custom-gcl"). If directory creation fails, the error is wrapped as "create temporary directory: %w". The temp dir is normally cleaned up afterwards unless the keep-temp-files env var is set.

Source

Thrown at pkg/commands/custom.go:88

	if c.opts.destination != "" {
		cfg.Destination = c.opts.destination
	}

	err = cfg.Validate()
	if err != nil {
		return err
	}

	c.cfg = cfg

	return nil
}

func (c *customCommand) runE(cmd *cobra.Command, _ []string) error {
	tmp, err := os.MkdirTemp(os.TempDir(), "custom-gcl")
	if err != nil {
		return fmt.Errorf("create temporary directory: %w", err)
	}

	defer func() {
		if os.Getenv(envKeepTempFiles) != "" {
			log.Printf("WARN: The env var %s has been detected: the temporary directory is preserved: %s", envKeepTempFiles, tmp)

			return
		}

		_ = os.RemoveAll(tmp)
	}()

	err = internal.NewBuilder(c.log, c.cfg, tmp).Build(cmd.Context())
	if err != nil {
		return fmt.Errorf("build process: %w", err)
	}

	return nil

View on GitHub (pinned to ed7a235d2d)

Solutions

  1. Check the wrapped %w error (os.PathError) for the path and errno (ENOENT, EACCES, ENOSPC)
  2. Verify/set TMPDIR to an existing writable directory (echo $TMPDIR; mkdir -p $TMPDIR)
  3. Free disk space if the error is 'no space left on device'
  4. In restricted containers, ensure /tmp (or $TMPDIR) is mounted writable
  5. Clear out leftover custom-gcl* directories if /tmp is cluttered

Example fix

// before (CI)
TMPDIR=/nonexistent golangci-lint custom
// create temporary directory: mkdir /nonexistent/custom-gcl...: no such file or directory

// after
export TMPDIR=$(mktemp -d)
golangci-lint custom
Defensive patterns

Strategy: fallback

Validate before calling

tmpBase := os.TempDir()
if info, err := os.Stat(tmpBase); err != nil || !info.IsDir() {
    return fmt.Errorf("temp dir %s unusable (check TMPDIR)", tmpBase)
}
probe, err := os.CreateTemp(tmpBase, "write-probe")
if err != nil {
    return fmt.Errorf("temp dir %s not writable: %w", tmpBase, err)
}
_ = os.Remove(probe.Name())
_ = probe.Close()

Type guard

func isMkdirTempError(err error) (string, bool) {
    var pe *os.PathError
    if errors.As(err, &pe) {
        return pe.Path, true
    }
    return "", false
}

Try / catch

tmp, err := os.MkdirTemp(os.TempDir(), "custom-gcl")
if err != nil {
    if errors.Is(err, fs.ErrPermission) || errors.Is(err, syscall.ENOSPC) {
        return fmt.Errorf("fix TMPDIR or free disk space: %w", err)
    }
    return fmt.Errorf("create temporary directory: %w", err)
}

Prevention

When it happens

Trigger: os.MkdirTemp(os.TempDir(), "custom-gcl") fails while running the custom subcommand — TMPDIR points to a nonexistent/unwritable location, disk full, or too many open files.

Common situations: TMPDIR env var set to an invalid path in CI; read-only /tmp in containers; disk quota exceeded; SELinux/AppArmor blocking writes to the temp dir; /tmp filled by prior failed builds.

Related errors


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