gatsbyjs/gatsby · error · Error

Failed to write ${file} into ${outputPath}. (${err.message})

Error message

Failed to write ${file} into ${outputPath}. (${err.message})

What it means

During each transform, process-file.ts runs the cloned sharp pipeline to a buffer and writes it to outputPath. If toBuffer fails (sharp could not encode, e.g. unsupported output format or processing error mid-pipeline) or fs.writeFile fails (disk full, permission denied, missing parent dir despite ensureDir), the error is re-thrown with the input file, the output path, and the underlying message.

Source

Thrown at packages/gatsby-plugin-sharp/src/process-file.ts:136

        // rotate
        if (transformArgs.rotate && transformArgs.rotate !== 0) {
          clonedPipeline = clonedPipeline.rotate(transformArgs.rotate)
        }

        // duotone
        if (transformArgs.duotone) {
          clonedPipeline = await duotone(
            transformArgs.duotone,
            transformArgs.toFormat,
            clonedPipeline
          )
        }

        try {
          const buffer = await clonedPipeline.toBuffer()
          await fs.writeFile(outputPath, buffer)
        } catch (err) {
          throw new Error(
            `Failed to write ${file} into ${outputPath}. (${err.message})`
          )
        }
      } catch (err) {
        if (err instanceof SharpError) {
          // rethrow
          throw err
        }

        throw new SharpError(`Processing ${file} failed`, err)
      }

      return transform
    })
  )
}

export const createArgsDigest = (args: unknown): string => {

View on GitHub (pinned to 8b06340921)

Solutions

  1. Check free disk space and write permissions on the output/cache directory (df -h, ls -la .cache/public).
  2. Run gatsby clean to remove a possibly-corrupted .cache/public and retry.
  3. If using avif/webp, rebuild sharp with codec support or fall back to jpg/png.
  4. Reduce concurrent jobs / parallelism if multiple builds share the output dir.
  5. Inspect err.message (surfaced in the error) to distinguish encoding vs. filesystem failure.
Defensive patterns

Strategy: try-catch

Validate before calling

const fs = require('fs'); const path = require('path');
function assertWritableOutput(outputPath) {
  const dir = path.dirname(outputPath);
  fs.ensureDirSync?.(dir); // if fs-extra available
  const stat = fs.statSync(dir);
  if (!stat.isDirectory()) throw new Error(`Output dir not a directory: ${dir}`);
  fs.accessSync(dir, fs.constants.W_OK);
}

Type guard

function isWritableDir(p) {
  try { fs.accessSync(p, fs.constants.W_OK); return true; } catch { return false; }
}

Try / catch

try {
  await fs.writeFile(outputPath, buffer);
} catch (err) {
  if (err.code === 'ENOSPC') { reporter.panic('Out of disk space writing image output'); }
  if (err.code === 'EACCES') { reporter.panic(`Permission denied: ${outputPath}`); }
  throw err;
}

Prevention

When it happens

Trigger: Output directory becomes unwritable mid-build; disk full; outputPath is on a read-only mount; sharp fails to encode the requested format (e.g. avif without libheif); the transform produces an empty/invalid buffer; duotone/toFormat combination sharp cannot satisfy.

Common situations: CI runners out of disk; Docker bind mounts with wrong permissions; switching toFormat to avif/webp without a sharp build that supports it; concurrent builds writing to the same public dir.

Related errors


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