{"id":"b0dc5f1e0a9f0c88","repo":"babel/babel","slug":"caching-has-already-been-configured-with-forever","errorCode":null,"errorMessage":"Caching has already been configured with .forever()","messagePattern":"Caching has already been configured with \\.forever\\(\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/babel-core/src/config/caching.ts","lineNumber":290,"sourceCode":"  }\n\n  forever() {\n    if (!this._active) {\n      throw new Error(\"Cannot change caching after evaluation has completed.\");\n    }\n    if (this._never) {\n      throw new Error(\"Caching has already been configured with .never()\");\n    }\n    this._forever = true;\n    this._configured = true;\n  }\n\n  never() {\n    if (!this._active) {\n      throw new Error(\"Cannot change caching after evaluation has completed.\");\n    }\n    if (this._forever) {\n      throw new Error(\"Caching has already been configured with .forever()\");\n    }\n    this._never = true;\n    this._configured = true;\n  }\n\n  using<T>(handler: (data: SideChannel) => T): T {\n    if (!this._active) {\n      throw new Error(\"Cannot change caching after evaluation has completed.\");\n    }\n    if (this._never || this._forever) {\n      throw new Error(\n        \"Caching has already been configured with .never or .forever()\",\n      );\n    }\n    this._configured = true;\n\n    const key = handler(this._data);\n","sourceCodeStart":272,"sourceCodeEnd":308,"githubUrl":"https://github.com/babel/babel/blob/06b6eae39da4ce0689fad64e2c48a6375a464208/packages/babel-core/src/config/caching.ts#L272-L308","documentation":"Thrown by CacheConfigurator.never() when this._forever is already true. The mirror of error [4]: having already committed to forever caching, switching to never is forbidden because the forever entry is already immutable and would never be invalidated. Cache modes are set once.","triggerScenarios":"A factory calls api.cache.forever() (or api.cache(true)) and then api.cache.never() in the same invocation — both execute due to missing early return.","commonSituations":"Refactoring cache logic and leaving both calls; copy-paste of cache boilerplate; conditional branches where both paths run.","solutions":["Keep a single cache-mode call per factory invocation.","Delete the leftover .forever() call when switching to .never() (though .never() is discouraged).","Use api.cache(() => value) for conditional caching instead of imperatively flipping modes."],"exampleFix":"// before\nmodule.exports = function (api) {\n  api.cache.forever();\n  if (shouldInvalidate) api.cache.never(); // throws\n  return {};\n};\n\n// after\nmodule.exports = function (api) {\n  api.cache(() => !shouldInvalidate);\n  return {};\n};","handlingStrategy":"validation","validationCode":"module.exports = function (api) {\n  // Only one unconditional mode per invocation\n  api.cache.never();\n  // do NOT also call api.cache.forever() here\n  return { visitor: {} };\n};","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pick one cache mode and commit; do not call both never() and forever().","Use the keyed form api.cache(() => value) to avoid imperative mode flipping.","Code-review cache boilerplate during plugin refactors."],"tags":["caching","plugin","preset"],"analyzedSha":"06b6eae39da4ce0689fad64e2c48a6375a464208","analyzedAt":"2026-08-03T20:13:43.465Z","schemaVersion":2}