{"record":{"id":"b151eee3bfdf5157","repo":"gatsbyjs/gatsby","slug":"you-can-t-set-plugin-status-without-a-plugin","errorCode":null,"errorMessage":"You can't set plugin status without a plugin","messagePattern":"You can't set plugin status without a plugin","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/gatsby/src/redux/reducers/status.ts","lineNumber":35,"sourceCode":"    case `DELETE_CACHE`:\n      return {\n        ...defaultState,\n        cdnObfuscatedPrefix: state.cdnObfuscatedPrefix ?? ``,\n      }\n    case `INIT`: {\n      if (!state.cdnObfuscatedPrefix) {\n        state.cdnObfuscatedPrefix = uuid.v4()\n      }\n      return state\n    }\n    case `UPDATE_PLUGINS_HASH`:\n      return {\n        ...state,\n        PLUGINS_HASH: action.payload,\n      }\n    case `SET_PLUGIN_STATUS`:\n      if (!action.plugin || !action.plugin?.name) {\n        throw new Error(`You can't set plugin status without a plugin`)\n      }\n      if (!_.isObject(action.payload)) {\n        throw new Error(\n          `You must pass an object into setPluginStatus. What was passed in was ${JSON.stringify(\n            action.payload,\n            null,\n            4\n          )}`\n        )\n      }\n      return {\n        ...state,\n        plugins: {\n          ...state.plugins,\n          [action.plugin.name]: _.merge(\n            {},\n            state.plugins[action.plugin.name],\n            action.payload","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/gatsbyjs/gatsby/blob/8b06340921ffdf23125a365b9c9923690cb62ce6/packages/gatsby/src/redux/reducers/status.ts#L17-L53","documentation":"The status reducer's SET_PLUGIN_STATUS case stores per-plugin status under state.plugins[plugin.name]; it throws if action.plugin or action.plugin.name is missing because there is no key to store the status under. The public actions.setPluginStatus wrapper supplies the plugin automatically, so reaching this throw means the action was dispatched without plugin context.","triggerScenarios":"Dispatching SET_PLUGIN_STATUS with action.plugin undefined/null or action.plugin.name falsy. End users normally hit it only via setPluginStatus when the action context has been stripped (manual dispatch, misconfigured test harness).","commonSituations":"A plugin calling the internal store dispatch directly; a test mocking the store without plugin context; an outdated plugin relying on removed internal plumbing that no longer attaches plugin metadata.","solutions":["Call actions.setPluginStatus(...) from within a Gatsby Node API (onPreBootstrap, etc.) where plugin is bound.","If dispatching manually, include `plugin: { name: 'your-plugin' }` on the action.","Ensure you are on a compatible Gatsby version for the plugin in question."],"exampleFix":"// before\nstore.dispatch({ type: `SET_PLUGIN_STATUS`, payload: { lastRun: Date.now() } })\n// after\nstore.dispatch({ type: `SET_PLUGIN_STATUS`, plugin: { name: `my-plugin` }, payload: { lastRun: Date.now() } })","handlingStrategy":"validation","validationCode":"function safeSetPluginStatus(actions, plugin, payload) {\n  if (!plugin?.name) throw new Error('setPluginStatus requires plugin.name')\n  return actions.setPluginStatus(payload)\n}","typeGuard":"function hasPlugin(action) {\n  return !!action?.plugin?.name\n}","tryCatchPattern":null,"preventionTips":["Call actions.setPluginStatus only from within Gatsby Node APIs where plugin is bound.","When dispatching SET_PLUGIN_STATUS manually in tests, include plugin: { name }.","Validate plugin context at your plugin's entry points."],"tags":["status","reducer","plugin-context","validation"],"backgroundTag":null,"analyzedSha":"8b06340921ffdf23125a365b9c9923690cb62ce6","analyzedAt":"2026-08-13T02:36:21.405Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}