gatsbyjs/gatsby · error · Error
An ID must be provided when creating or setting job
Error message
An ID must be provided when creating or setting job
What it means
The jobs reducer (v1 job API) handles CREATE_JOB and SET_JOB by merging or pushing into state.jobs.active, keyed by payload.id. It throws at the top of that case if action.payload.id is falsy, because without an ID the job cannot be found, merged, deduplicated, or later ended. The ID is the correlation key for the entire job lifecycle.
Source
Thrown at packages/gatsby/src/redux/reducers/jobs.ts:15
import _ from "lodash"
import { oneLine } from "common-tags"
import moment from "moment"
import { IGatsbyState, ActionsUnion } from "../types"
export const jobsReducer = (
state: IGatsbyState["jobs"] = { active: [], done: [] },
action: ActionsUnion
): IGatsbyState["jobs"] => {
switch (action.type) {
case `CREATE_JOB`:
case `SET_JOB`: {
if (!action.payload.id) {
throw new Error(`An ID must be provided when creating or setting job`)
}
const index = _.findIndex(state.active, j => j.id === action.payload.id)
if (index !== -1) {
const mergedJob = _.merge(state.active[index], {
...action.payload,
createdAt: Date.now(),
plugin: action.plugin,
})
state.active[index] = mergedJob
return state
} else {
state.active.push({
...action.payload,
createdAt: Date.now(),
plugin: action.plugin,
})
return stateView on GitHub (pinned to 8b06340921)
Solutions
- Always pass a stable, unique `id` (e.g. derived from a content digest) when creating/setting a job.
- Prefer the v2 job API (createJobV2) over the legacy jobs actions; it validates inputs differently.
- If you do not need background job tracking, remove the call entirely.
Example fix
// before
actions.createJob({ name: `resize`, outputDir }) // no id
// after
actions.createJob({ id: createContentDigest({ outputDir, input }), name: `resize`, outputDir }) Defensive patterns
Strategy: validation
Validate before calling
// Always derive a stable id before createJob/setJob.
const crypto = require('crypto')
function jobId(input) {
if (!input || (typeof input !== 'object')) throw new Error('job input required')
return input.id || crypto.createHash('sha1').update(JSON.stringify(input)).digest('hex')
}
// actions.createJob({ id: jobId(payload), ...payload }) Type guard
function isValidJobPayload(p) {
return !!p && typeof p === 'object' && typeof p.id === 'string' && p.id.length > 0
} Prevention
- Generate ids from a content digest so they are stable and unique.
- Prefer the v2 createJobV2 API over the legacy jobs helpers.
- Validate required action fields at the boundary of your own plugin code.
When it happens
Trigger: Dispatching (or having a plugin dispatch) a CREATE_JOB / SET_JOB action whose payload lacks `id`. Normally reached only via internal helper APIs like actions.createJob / actions.setJob that wrap the dispatch; passing no/empty id to those wrappers reproduces it.
Common situations: A custom plugin calling the deprecated internal job API (jobs.createJob/setJob) without an id; a third-party plugin written against an older internal API surface; programmatic misuse of the redux store directly.
Related errors
- An ID must be provided when ending a job
- The plugin "${_.get(action, `plugin.name`, `anonymous`)}" tr
- You must pass an object into setPluginStatus. What was passe
- generateImageSource must be a function
- If you encounter this error, it's probably a Gatsby internal
AI-assisted analysis of gatsbyjs/gatsby@8b06340921 (2026-08-13).
Data as JSON: /api/errors/33ef50d5a5ebaa7f.
Report an issue: GitHub.