{"record":{"id":"195e05620abf82e9","repo":"mochajs/mocha","slug":"err-mocha-invalid-plugin-implementation","errorCode":"ERR_MOCHA_INVALID_PLUGIN_IMPLEMENTATION","errorMessage":"mochaHooks must be an object or a function returning (or fulfilling with) an object","messagePattern":"mochaHooks must be an object or a function returning \\(or fulfilling with\\) an object","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/plugin-loader.js","lineNumber":44,"sourceCode":" */\n\n/**\n * Built-in plugin definitions.\n */\nconst MochaPlugins = [\n  /**\n   * Root hook plugin definition\n   * @type {PluginDefinition}\n   */\n  {\n    exportName: \"mochaHooks\",\n    optionName: \"rootHooks\",\n    validate(value) {\n      if (\n        Array.isArray(value) ||\n        (typeof value !== \"function\" && typeof value !== \"object\")\n      ) {\n        throw createInvalidPluginImplementationError(\n          `mochaHooks must be an object or a function returning (or fulfilling with) an object`,\n        );\n      }\n    },\n    async finalize(rootHooks) {\n      if (rootHooks.length) {\n        const rootHookObjects = await Promise.all(\n          rootHooks.map(async (hook) =>\n            typeof hook === \"function\" ? hook() : hook,\n          ),\n        );\n\n        return rootHookObjects.reduce(\n          (acc, hook) => {\n            hook = {\n              beforeAll: [],\n              beforeEach: [],\n              afterAll: [],","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/mochajs/mocha/blob/6bcbee4fd9a95351cedf0fdcb14c7d696486bc5a/lib/plugin-loader.js#L26-L62","documentation":"The plugin loader's `mochaHooks` definition validate() (lib/plugin-loader.js:44) throws ERR_MOCHA_INVALID_PLUGIN_IMPLEMENTATION when a root hook implementation is neither a function nor a plain object (arrays are explicitly rejected). mochaHooks must be an object of hook arrays/functions or a function returning (or fulfilling with) such an object.","triggerScenarios":"Exporting `mochaHooks` as an array (e.g. `[beforeEach, afterEach]`), as a string/number, or forgetting to export it correctly so the loader receives the wrong type; also when an async factory returns something other than an object.","commonSituations":"Config in `.mocharc` `rootHooks` pointing at a module whose default export shape changed; migrating from arrays of hooks to the mochaHooks object convention; TypeScript files exporting hooks in the wrong shape.","solutions":["Export `mochaHooks` as an object keyed by hook name, e.g. `exports.mochaHooks = { beforeEach: [ ... ] }`.","If a function, make it return (or fulfill with) a hooks object.","If you have an array, convert it to an object like `{ beforeEach: [...] }`.","Verify the `rootHooks` config path points to the intended module."],"exampleFix":"// before\nexports.mochaHooks = [beforeEachHook, afterEachHook];\n// after\nexports.mochaHooks = { beforeEach: [beforeEachHook], afterEach: [afterEachHook] };","handlingStrategy":"validation","validationCode":"const hooks = require('./global-hooks');\nconst v = hooks.mochaHooks;\nconst ok = !Array.isArray(v) && (typeof v === 'function' || typeof v === 'object' && v !== null);\nif (!ok) throw new Error('mochaHooks must be an object or function returning an object');","typeGuard":"function isValidMochaHooks(v) {\n  return !Array.isArray(v) && (typeof v === 'function' || (typeof v === 'object' && v !== null));\n}","tryCatchPattern":"try {\n  await mocha.loadRootHooks();\n} catch (err) {\n  if (err.code === 'ERR_MOCHA_INVALID_PLUGIN_IMPLEMENTATION') {\n    console.error('Fix exports.mochaHooks shape: object or function returning object');\n  } else throw err;\n}","preventionTips":["Export mochaHooks as { beforeEach: [...], afterEach: [...] }","Never export arrays for rootHooks","Verify module path in .mocharc rootHooks option"],"tags":["plugins","root-hooks","configuration"],"backgroundTag":"invalid-plugin-implementation","analyzedSha":"6bcbee4fd9a95351cedf0fdcb14c7d696486bc5a","analyzedAt":"2026-09-01T03:41:47.182Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}