gatsbyjs/gatsby · error · Error

Could not find matching operation for ${requestedPathOnDisk}

Error message

Could not find matching operation for ${requestedPathOnDisk}

What it means

In gatsby-plugin-sharp, when a request comes in for a specific transformed image on disk, splitOperationsByRequestedFile walks the job's operations and partitions them into the one matching requestedPathOnDisk and the rest. If no operation's resolved outputPath equals the requested path, nothing was scheduled for that file and the function throws. This is an internal job-consistency error, not something caused by user image options directly.

Source

Thrown at packages/gatsby-plugin-sharp/src/gatsby-node.js:98

  const matchingJob = {
    ...job,
    args: { ...job.args, operations: [] },
  }
  const jobWithRemainingOperations = {
    ...job,
    args: { ...job.args, operations: [] },
  }

  job.args.operations.forEach(op => {
    const operationPath = path.resolve(path.join(job.outputDir, op.outputPath))
    if (operationPath === requestedPathOnDisk) {
      matchingJob.args.operations.push(op)
    } else {
      jobWithRemainingOperations.args.operations.push(op)
    }
  })
  if (matchingJob.args.operations.length === 0) {
    throw new Error(
      `Could not find matching operation for ${requestedPathOnDisk}`
    )
  }
  return { matchingJob, jobWithRemainingOperations }
}

// So something is wrong with the reporter, when I do this in preBootstrap,
// the progressbar gets not updated
exports.onPostBootstrap = async ({ reporter, cache, store }) => {
  if (process.env.gatsby_executing_command !== `develop`) {
    // recreate jobs that haven't been triggered by develop yet
    // removing stale jobs has already kicked in so we know these still need to process
    for (const [contentDigest] of store.getState().jobsV2.complete) {
      const job = await cache.get(contentDigest)

      if (job) {
        // we don't have to await, gatsby does this for us
        _unstable_createJob(job, { reporter })

View on GitHub (pinned to 8b06340921)

Solutions

  1. Run `gatsby clean` to remove .cache and public, then rebuild so jobs and outputs are consistent.
  2. If you cache transformed image URLs client-side, bust that cache (rename or version the URL).
  3. Ensure outputDir and outputPath use consistent path separators; on Windows normalize with path.posix.
  4. If it reproduces after a clean build, report it to gatsby-plugin-sharp with the requested path and the job's operations.
Defensive patterns

Strategy: fallback

Validate before calling

function hasMatchingOperation(job, requestedPathOnDisk) {
  return job.args.operations.some(op =>
    path.resolve(path.join(job.outputDir, op.outputPath)) === requestedPathOnDisk
  );
}

Type guard

function jobCoversPath(job, requestedPathOnDisk) {
  return Array.isArray(job?.args?.operations) &&
    job.args.operations.some(op =>
      path.resolve(path.join(job.outputDir, op.outputPath)) === requestedPathOnDisk
    );
}

Try / catch

try {
  const { matchingJob, jobWithRemainingOperations } = splitOperationsByRequestedFile(job, req);
} catch (e) {
  // Stale cache request: 404 to the client and let the next build regenerate.
  res.status(404).end();
  return;
}

Prevention

When it happens

Trigger: A develop/build request asks for an image output that is not part of any queued sharp job: stale cache entries pointing at deleted operations, a public/ dir manually edited, a path mismatch between outputPath casing on case-sensitive filesystems, or a bug where requestedPathOnDisk was resolved against a different outputDir than the job.

Common situations: Browser requests a previously-generated derivative after the source image or its transform args changed; CDN/proxy caching an old URL; running `gatsby develop` over a `public/` folder from a prior build; cross-platform path separator mismatches (Windows vs POSIX).

Related errors


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