{"record":{"id":"5d469a7c0c9e41f4","repo":"jestjs/jest","slug":"watch-plugin-configuration-error-error","errorCode":null,"errorMessage":"Watch plugin configuration error:\n\n${error}","messagePattern":"Watch plugin configuration error:\n\n(.+?)","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"packages/jest-core/src/watch.ts","lineNumber":514,"sourceCode":"  Watch plugin ${chalk.bold.red(\n    getPluginIdentifier(plugin),\n  )} attempted to register key ${chalk.bold.red(`<${key}>`)},\n  that is reserved internally for ${chalk.bold.red(\n    conflictor.forbiddenOverwriteMessage,\n  )}.\n  Please change the configuration key for this plugin.`.trim();\n  } else {\n    const plugins = [conflictor.plugin, plugin]\n      .map(p => chalk.bold.red(getPluginIdentifier(p)))\n      .join(' and ');\n    error = `\n  Watch plugins ${plugins} both attempted to register key ${chalk.bold.red(\n    `<${key}>`,\n  )}.\n  Please change the key configuration for one of the conflicting plugins to avoid overlap.`.trim();\n  }\n\n  throw new ValidationError('Watch plugin configuration error', error);\n};\n\nconst getPluginIdentifier = (plugin: WatchPlugin) =>\n  // This breaks as `displayName` is not defined as a static, but since\n  // WatchPlugin is an interface, and it is my understanding interface\n  // static fields are not definable anymore, no idea how to circumvent\n  // this :-(\n  // @ts-expect-error: leave `displayName` be.\n  plugin.constructor.displayName || plugin.constructor.name;\n\nconst getPluginKey = (\n  plugin: WatchPlugin,\n  globalConfig: Config.GlobalConfig,\n) => {\n  if (typeof plugin.getUsageInfo === 'function') {\n    return (plugin.getUsageInfo(globalConfig) || {key: null}).key;\n  }\n","sourceCodeStart":496,"sourceCodeEnd":532,"githubUrl":"https://github.com/jestjs/jest/blob/8e6d128e4a278059ecddecaa97400b04c8ae5fd9/packages/jest-core/src/watch.ts#L496-L532","documentation":"Thrown as a ValidationError when two watch plugins attempt to register the same key, or when a plugin tries to register a key that is reserved internally by Jest. The conflict is detected during key registration in `determineWatchPlugins`/`updateKeypressHandler` and names both conflicting plugins or the reserved key name.","triggerScenarios":"Configuring two `watchPlugins` entries in jest.config that both claim the same key (e.g. both return `{key: 'f'}` from `getUsageInfo`), or a custom plugin returning a key like `q` or `u` that Jest reserves internally. Also triggered when a plugin sets `overwritable: false` (default) and another plugin tries to use the same key.","commonSituations":"Installing multiple community watch plugins that overlap on default keys. Writing a custom watch plugin and unknowingly using a key Jest already binds. Upgrading a plugin whose default key changed to collide with another.","solutions":["Read the error message — it names both conflicting plugins and the disputed key.","Change the key configuration for one of the plugins in your jest.config `watchPlugins` array (pass a different key as the plugin's config option).","If a plugin attempts a reserved key, the message names the reserved purpose — pick a non-reserved key.","Remove one of the conflicting watch plugins if both are not needed."],"exampleFix":"// before: jest.config.js — both plugins use 'p'\nmodule.exports = {\n  watchPlugins: [\n    ['jest-watch-typeahead/filename', { key: 'p' }],\n    ['jest-watch-select-projects', { key: 'p' }],\n  ],\n};\n\n// after: give each a unique key\nmodule.exports = {\n  watchPlugins: [\n    ['jest-watch-typeahead/filename', { key: 'f' }],\n    ['jest-watch-select-projects', { key: 'p' }],\n  ],\n};","handlingStrategy":"validation","validationCode":"// Before Jest starts, check watch plugin keys for collisions\nfunction validateWatchPluginKeys(plugins) {\n  const keys = new Map();\n  for (const [name, opts] of plugins) {\n    const key = opts?.key;\n    if (!key) continue;\n    if (keys.has(key)) {\n      throw new Error(`Key '${key}' is used by both ${keys.get(key)} and ${name}`);\n    }\n    keys.set(key, name);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Review the default key of each watch plugin before adding multiple to the config.","Explicitly assign unique keys to each plugin in the watchPlugins config array.","Avoid using reserved Jest keys (q, u, f, t, o, i, p, w, a, e) for custom plugins."],"tags":["jest-core","watch-mode","watch-plugins","configuration"],"backgroundTag":null,"analyzedSha":"8e6d128e4a278059ecddecaa97400b04c8ae5fd9","analyzedAt":"2026-08-10T18:11:27.960Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}