mochajs/mocha · error · Error

ERR_MOCHA_INVALID_PLUGIN_IMPLEMENTATION

ERR_MOCHA_INVALID_PLUGIN_IMPLEMENTATION

Error message

mochaHooks must be an object or a function returning (or fulfilling with) an object

What it means

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.

Source

Thrown at lib/plugin-loader.js:44

 */

/**
 * Built-in plugin definitions.
 */
const MochaPlugins = [
  /**
   * Root hook plugin definition
   * @type {PluginDefinition}
   */
  {
    exportName: "mochaHooks",
    optionName: "rootHooks",
    validate(value) {
      if (
        Array.isArray(value) ||
        (typeof value !== "function" && typeof value !== "object")
      ) {
        throw createInvalidPluginImplementationError(
          `mochaHooks must be an object or a function returning (or fulfilling with) an object`,
        );
      }
    },
    async finalize(rootHooks) {
      if (rootHooks.length) {
        const rootHookObjects = await Promise.all(
          rootHooks.map(async (hook) =>
            typeof hook === "function" ? hook() : hook,
          ),
        );

        return rootHookObjects.reduce(
          (acc, hook) => {
            hook = {
              beforeAll: [],
              beforeEach: [],
              afterAll: [],

View on GitHub (pinned to 6bcbee4fd9)

Solutions

  1. Export `mochaHooks` as an object keyed by hook name, e.g. `exports.mochaHooks = { beforeEach: [ ... ] }`.
  2. If a function, make it return (or fulfill with) a hooks object.
  3. If you have an array, convert it to an object like `{ beforeEach: [...] }`.
  4. Verify the `rootHooks` config path points to the intended module.

Example fix

// before
exports.mochaHooks = [beforeEachHook, afterEachHook];
// after
exports.mochaHooks = { beforeEach: [beforeEachHook], afterEach: [afterEachHook] };
Defensive patterns

Strategy: validation

Validate before calling

const hooks = require('./global-hooks');
const v = hooks.mochaHooks;
const ok = !Array.isArray(v) && (typeof v === 'function' || typeof v === 'object' && v !== null);
if (!ok) throw new Error('mochaHooks must be an object or function returning an object');

Type guard

function isValidMochaHooks(v) {
  return !Array.isArray(v) && (typeof v === 'function' || (typeof v === 'object' && v !== null));
}

Try / catch

try {
  await mocha.loadRootHooks();
} catch (err) {
  if (err.code === 'ERR_MOCHA_INVALID_PLUGIN_IMPLEMENTATION') {
    console.error('Fix exports.mochaHooks shape: object or function returning object');
  } else throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of mochajs/mocha@6bcbee4fd9 (2026-09-01). Data as JSON: /api/errors/195e05620abf82e9. Report an issue: GitHub.