{"id":"243a3215f24f93d8","repo":"babel/babel","slug":"caching-has-already-been-configured-with-never","errorCode":null,"errorMessage":"Caching has already been configured with .never()","messagePattern":"Caching has already been configured with \\.never\\(\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/babel-core/src/config/caching.ts","lineNumber":279,"sourceCode":"  }\n\n  simple() {\n    return makeSimpleConfigurator(this);\n  }\n\n  mode() {\n    if (this._never) return \"never\";\n    if (this._forever) return \"forever\";\n    if (this._invalidate) return \"invalidate\";\n    return \"valid\";\n  }\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) {","sourceCodeStart":261,"sourceCodeEnd":297,"githubUrl":"https://github.com/babel/babel/blob/06b6eae39da4ce0689fad64e2c48a6375a464208/packages/babel-core/src/config/caching.ts#L261-L297","documentation":"Thrown by CacheConfigurator.forever() when this._never is already true. Babel cache modes are mutually exclusive: once you declare .never() the configurator forbids switching to .forever(), because the two modes produce incompatible cache entries (never = re-evaluate every time, forever = evaluate once and memoise permanently).","triggerScenarios":"A plugin/preset factory calls api.cache.never() and then api.cache.forever() (or api.cache(false) followed by api.cache(true)) in the same invocation. Both branches execute because they are not guarded by an early return.","commonSituations":"Conditionally choosing cache mode with if/else where both calls accidentally execute; copy-pasting cache boilerplate and forgetting to delete the previous line; refactoring that leaves a stale cache call.","solutions":["Ensure only one cache mode is set per factory invocation; use a single api.cache(...) call guarded by early returns.","Delete the stale .never() call left behind after switching to .forever().","Prefer api.cache(() => condition) for environment-dependent caching instead of imperatively branching between never/forever."],"exampleFix":"// before\nmodule.exports = function (api) {\n  api.cache.never();\n  if (process.env.NODE_ENV === \"production\") api.cache.forever(); // throws\n  return {};\n};\n\n// after\nmodule.exports = function (api) {\n  api.cache(() => process.env.NODE_ENV === \"production\");\n  return {};\n};","handlingStrategy":"validation","validationCode":"module.exports = function (api) {\n  // Set exactly one mode, guarded by early return\n  if (process.env.NODE_ENV === \"test\") {\n    api.cache.never();\n    return { /* test config */ };\n  }\n  api.cache.forever();\n  return { /* prod config */ };\n};","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use a single api.cache(...) call per factory invocation.","Prefer the functional form api.cache(() => condition) over imperative never/forever.","Lint your config for duplicate cache calls."],"tags":["caching","plugin","preset"],"analyzedSha":"06b6eae39da4ce0689fad64e2c48a6375a464208","analyzedAt":"2026-08-03T20:13:43.465Z","schemaVersion":2}