{"record":{"id":"6185c51c69181f51","repo":"gatsbyjs/gatsby","slug":"if-you-encounter-this-error-it-s-probably-a-gatsb","errorCode":null,"errorMessage":"If you encounter this error, it's probably a Gatsby internal bug. Please open an issue reporting us this.","messagePattern":"If you encounter this error, it's probably a Gatsby internal bug\\. Please open an issue reporting us this\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/gatsby/src/redux/reducers/jobsv2.ts","lineNumber":64,"sourceCode":"\n    case `CREATE_JOB_V2`: {\n      const { job } = action.payload\n\n      state.incomplete.set(job.contentDigest, {\n        job,\n      } as IGatsbyIncompleteJobV2)\n\n      return state\n    }\n\n    case `END_JOB_V2`: {\n      const { jobContentDigest, result } = action.payload\n      const { job } = state.incomplete.get(\n        jobContentDigest\n      ) as IGatsbyIncompleteJobV2\n\n      if (!job) {\n        throw new Error(\n          `If you encounter this error, it's probably a Gatsby internal bug. Please open an issue reporting us this.`\n        )\n      }\n\n      state.incomplete.delete(job.contentDigest)\n\n      // inputPaths is used to make sure the job is not stale\n      state.complete.set(job.contentDigest, {\n        result,\n        inputPaths: job.inputPaths,\n      } as IGatsbyCompleteJobV2)\n\n      return state\n    }\n\n    case `REMOVE_STALE_JOB_V2`: {\n      const { contentDigest } = action.payload\n      state.incomplete.delete(contentDigest)","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/gatsbyjs/gatsby/blob/8b06340921ffdf23125a365b9c9923690cb62ce6/packages/gatsby/src/redux/reducers/jobsv2.ts#L46-L82","documentation":"The v2 jobs reducer's END_JOB_V2 case reads state.jobsV2.incomplete.get(jobContentDigest) and destructures `{ job }` from it; if no incomplete job exists for that digest, `job` is undefined and the reducer throws, telling the user this is almost certainly a Gatsby internal bug. The v2 API keys jobs by contentDigest, and END_JOB_V2 should always have a matching START_JOB_V2 predecessor in the same build.","triggerScenarios":"Dispatching END_JOB_V2 with a jobContentDigest that is absent from state.incomplete (never started, or already completed and deleted). The incomplete map is mutated (delete on completion), so a duplicate end also misses.","commonSituations":"Genuinely rare; indicates out-of-order dispatch, replayed actions after a partial cache, or a regression in the v2 job orchestration. End users essentially cannot cause this through normal plugin APIs - it is a guard for invariant violations inside Gatsby's job runner.","solutions":["Report the issue to Gatsby with a reproduction (the message explicitly asks for this).","Clear .cache and public and rebuild to reset the v2 job maps.","Update to the latest Gatsby patch release in case it is a fixed internal bug.","If you maintain a plugin calling internal v2 job actions directly, ensure END_JOB_V2 only fires after a successful START_JOB_V2 with the same digest."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// This signals a Gatsby internal bug; surface and reset rather than swallow.\ntry {\n  // ... v2 job lifecycle ...\n} catch (e) {\n  if (/probably a Gatsby internal bug/.test(e.message)) {\n    report.error(e)\n    // recommend gatsby clean + rebuild\n  } else throw e\n}","preventionTips":["Do not call internal v2 redux actions (START_JOB_V2 / END_JOB_V2) directly; use the public createJobV2 API.","Keep Gatsby updated to pick up internal fixes.","Run gatsby clean when job state looks inconsistent."],"tags":["jobs","jobsv2","reducer","internal-bug"],"backgroundTag":null,"analyzedSha":"8b06340921ffdf23125a365b9c9923690cb62ce6","analyzedAt":"2026-08-13T02:36:21.405Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}