{"record":{"id":"3cbd113f9bce34cd","repo":"gatsbyjs/gatsby","slug":"usage-of-cache-instance-in-onpreinit-api-is-no","errorCode":null,"errorMessage":"Usage of \"cache\" instance in \"onPreInit\" API is not supported as this API runs before cache initialization (called in ${plugin})","messagePattern":"Usage of \"cache\" instance in \"onPreInit\" API is not supported as this API runs before cache initialization \\(called in (.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/gatsby/src/utils/api-runner-node.js","lineNumber":303,"sourceCode":"        originalDone.apply(activity)\n        runningActivities.delete(activity)\n      }\n\n      return activity\n    },\n  }\n}\n\nconst getUninitializedCache = plugin => {\n  const message =\n    `Usage of \"cache\" instance in \"onPreInit\" API is not supported as ` +\n    `this API runs before cache initialization` +\n    (plugin && plugin !== `default-site-plugin` ? ` (called in ${plugin})` : ``)\n\n  return {\n    // GatsbyCache\n    async get() {\n      throw new Error(message)\n    },\n    async set() {\n      throw new Error(message)\n    },\n    async del() {\n      throw new Error(message)\n    },\n  }\n}\n\nconst availableActionsCache = new Map()\nlet publicPath\nconst runAPI = async (plugin, api, args, activity) => {\n  const gatsbyNode = await importGatsbyPlugin(plugin, `gatsby-node`)\n\n  if (gatsbyNode[api]) {\n    const parentSpan = args && args.parentSpan\n    const spanOptions = parentSpan ? { childOf: parentSpan } : {}","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/gatsbyjs/gatsby/blob/8b06340921ffdf23125a365b9c9923690cb62ce6/packages/gatsby/src/utils/api-runner-node.js#L285-L321","documentation":"The cache instance handed to plugins during onPreInit is a stub because the real cache (LMDB) is not initialized until after onPreInit runs. Any cache.get() call inside onPreInit throws, naming the offending plugin.","triggerScenarios":"A plugin's onPreInit hook calls cache.get(...) (reading a previously stored value).","commonSituations":"Plugin migrated cache reads from onPreBootstrap into onPreInit; misordered lifecycle usage; plugin assuming cache is available everywhere.","solutions":["Move cache reads to onPreBootstrap (or any later lifecycle hook).","Defer the work that needs the cache with a callback/queue flushed in onPreBootstrap.","Use a transient in-memory placeholder during onPreInit and reconcile against the cache later."],"exampleFix":"// before: throws in onPreInit\nexports.onPreInit = async ({ cache }) => {\n  const v = await cache.get('key')\n}\n// after: move to onPreBootstrap\nexports.onPreBootstrap = async ({ cache }) => {\n  const v = await cache.get('key')\n}","handlingStrategy":"validation","validationCode":"// Guard cache reads in any onPreInit hook\nexports.onPreInit = async ({ cache }) => {\n  // cache is a stub here; do NOT call cache.get in onPreInit\n  // schedule the read for onPreBootstrap instead\n}","typeGuard":"function isRealCache(cache) {\n  return typeof cache.get === 'function' && cache.get.toString().indexOf('throw') === -1\n}","tryCatchPattern":null,"preventionTips":["Only touch cache in onPreBootstrap or later lifecycle hooks.","Queue cache work during onPreInit and flush it once the cache is real.","Lint your plugin for cache.* calls inside onPreInit."],"tags":["cache","lifecycle","plugin"],"backgroundTag":null,"analyzedSha":"8b06340921ffdf23125a365b9c9923690cb62ce6","analyzedAt":"2026-08-13T02:36:21.405Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}