gatsbyjs/gatsby · critical

Unable to copy site files to .cache

Error message

Unable to copy site files to .cache

What it means

During initialization Gatsby copies site files (source plugins, config) into the .cache directory and sets up the LMDB cache and fragments directory. If any of these filesystem operations fail (permission denied, disk full, path too long, antivirus lock), it panics with the underlying error attached.

Source

Thrown at packages/gatsby/src/services/initialize.ts:501

  })

  activity.start()

  const srcDir = `${__dirname}/../../cache-dir`
  const siteDir = cacheDirectory

  try {
    await fs.copy(srcDir, siteDir, {
      overwrite: true,
    })
    await fs.ensureDir(`${cacheDirectory}/${lmdbCacheDirectoryName}`)

    // Ensure .cache/fragments exists and is empty. We want fragments to be
    // added on every run in response to data as fragments can only be added if
    // the data used to create the schema they're dependent on is available.
    await fs.emptyDir(`${cacheDirectory}/fragments`)
  } catch (err) {
    reporter.panic(`Unable to copy site files to .cache`, err)
  }

  // Find plugins which implement gatsby-browser and gatsby-ssr and write
  // out api-runners for them.
  const hasAPIFile = (env, plugin): string | undefined => {
    // The plugin loader has disabled SSR APIs for this plugin. Usually due to
    // multiple implementations of an API that can only be implemented once
    if (env === `ssr` && plugin.skipSSR === true) return undefined

    const envAPIs = plugin[`${env}APIs`]

    // Always include gatsby-browser.js files if they exist as they're
    // a handy place to include global styles and other global imports.
    try {
      if (env === `browser`) {
        const modulePath = path.join(plugin.resolve, `gatsby-${env}`)
        return slash(resolveModule(modulePath) as string)
      }

View on GitHub (pinned to 8b06340921)

Solutions

  1. Run `gatsby clean` (or manually delete .cache) to remove any corrupt or locked cache state.
  2. Check filesystem permissions on the project directory -- ensure the Node process has read/write access.
  3. Free disk space if the volume is full.
  4. On Windows, temporarily disable antivirus scanning of the project folder or add an exclusion for .cache.
  5. Inspect the attached `err` object for the specific filesystem error code (EACCES, ENOSPC, EPERM, etc.).
Defensive patterns

Strategy: try-catch

Validate before calling

// Check write permissions and disk space before building
const fs = require('fs-extra')
const os = require('os')

async function preBuildCheck(cacheDir) {
  try {
    await fs.ensureDir(cacheDir)
    await fs.writeFile(cacheDir + '/.write-test', 'ok')
    await fs.remove(cacheDir + '/.write-test')
  } catch {
    throw new Error('Cache directory ' + cacheDir + ' is not writable')
  }
}

Prevention

When it happens

Trigger: The fs.copy(srcDir, siteDir) or fs.ensureDir/fs.emptyDir for .cache throws -- due to permissions, disk space, file locks (Windows antivirus), or a corrupt/locked .cache directory.

Common situations: Windows with aggressive antivirus locking files in .cache. Read-only filesystem or insufficient permissions in the project directory. Disk full. A previous crashed build left .cache in a locked/corrupt state. Symlink or path-length limits on Windows.

Related errors


AI-assisted analysis of gatsbyjs/gatsby@8b06340921 (2026-08-13). Data as JSON: /api/errors/3383dbf6c53e1fdd. Report an issue: GitHub.