golangci/golangci-lint · error

failed to build packages cache: %w

Error message

failed to build packages cache: %w

What it means

Before linting, golangci-lint builds an on-disk packages cache (`cache.NewCache`). If cache initialization fails — typically because the user cache directory cannot be determined or created — the error is wrapped as `failed to build packages cache: %w`. Without this cache the run cannot proceed.

Source

Thrown at pkg/commands/run.go:203

	}

	c.dbManager = dbManager

	c.printer, err = printers.NewPrinter(c.log, &c.cfg.Output.Formats, c.reportData, c.cfg.GetBasePath())
	if err != nil {
		return err
	}

	c.goenv = goutil.NewEnv(c.log.Child(logutils.DebugKeyGoEnv))

	c.fileCache = fsutils.NewFileCache()
	c.lineCache = fsutils.NewLineCache(c.fileCache)

	sw := timeutils.NewStopwatch("pkgcache", c.log.Child(logutils.DebugKeyStopwatch))

	pkgCache, err := cache.NewCache(sw, c.log.Child(logutils.DebugKeyPkgCache))
	if err != nil {
		return fmt.Errorf("failed to build packages cache: %w", err)
	}

	guard := load.NewGuard()

	pkgLoader := lint.NewPackageLoader(c.log.Child(logutils.DebugKeyLoader), c.cfg, args, c.goenv, guard)

	c.contextBuilder = lint.NewContextBuilder(c.cfg, pkgLoader, pkgCache, guard)

	if err = initHashSalt(c.log.Child(logutils.DebugKeyGoModSalt), c.buildInfo.Version, c.cfg); err != nil {
		return fmt.Errorf("failed to init hash salt: %w", err)
	}

	if ok := c.acquireFileLock(); !ok {
		return errors.New("parallel golangci-lint is running")
	}

	return nil
}

View on GitHub (pinned to ed7a235d2d)

Solutions

  1. Set a writable cache dir: export XDG_CACHE_HOME (or HOME) to an existing writable path.
  2. Create the cache directory: mkdir -p ~/.cache/golangci-lint and fix permissions with chown/chmod.
  3. Run the container with a writable volume mounted at the cache location (e.g. -v gocache:/root/.cache).
  4. Check disk space if the error indicates a full filesystem.
  5. Inspect the wrapped error after the message for the precise OS-level cause.

Example fix

// before (CI step)
- run: golangci-lint run   # HOME is unset in container
// after
- run: |
    export HOME=/tmp && mkdir -p $HOME/.cache
    golangci-lint run
Defensive patterns

Strategy: validation

Validate before calling

// ensure a writable cache dir exists before running
cacheDir := os.Getenv("XDG_CACHE_HOME")
if cacheDir == "" {
    home, err := os.UserHomeDir()
    if err != nil { return err }
    cacheDir = filepath.Join(home, ".cache")
}
if err := os.MkdirAll(filepath.Join(cacheDir, "golangci-lint"), 0o755); err != nil {
    return fmt.Errorf("cache dir not usable: %w", err)
}

Try / catch

if _, err := cache.NewCache(sw, log); err != nil {
    return fmt.Errorf("failed to build packages cache: %w", err) // check HOME/XDG_CACHE_HOME
}

Prevention

When it happens

Trigger: `cache.NewCache` failing because the OS cache directory (e.g. $XDG_CACHE_HOME, ~/.cache, %LocalAppData%) is unset and home is undiscoverable, unwritable, or on a full/read-only filesystem.

Common situations: CI containers running as non-root without a writable HOME; XDG_CACHE_HOME pointing to a non-existent dir; read-only root filesystems in Docker; NFS-mounted homes with permission issues; `HOME` unset in cron/systemd jobs.

Related errors


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