mochajs/mocha · error · TypeError (reporter) / Error (ui)

ERR_MOCHA_INVALID_REPORTER (reporter) or ERR_MOCHA_INVALID_INTERFACE (ui)

ERR_MOCHA_INVALID_REPORTER (reporter) or ERR_MOCHA_INVALID_INTERFACE (ui)

Error message

"--${pluginType}" can only be specified once

What it means

The --reporter and --ui flags are 'legacy plugins' and may only be given a single value. If the parsed option value is an array (the flag was specified multiple times), Mocha throws ERR_MOCHA_INVALID_REPORTER for --reporter or ERR_MOCHA_INVALID_INTERFACE for --ui. Repeat flags are ambiguous, so Mocha refuses to guess which one to use.

Source

Thrown at lib/cli/run-helpers.cjs:270

 * it actually exists. This must be run _after_ requires are processed (see
 * {@link handleRequires}), as it'll prevent interfaces from loading otherwise.
 * @param {Object} opts - Options object
 * @param {"reporter"|"ui"} pluginType - Type of plugin.
 * @param {Object} [map] - Used as a cache of sorts;
 * `Mocha.reporters` where each key corresponds to a reporter name,
 * `Mocha.interfaces` where each key corresponds to an interface name.
 * @private
 */
exports.validateLegacyPlugin = (opts, pluginType, map = {}) => {
  /**
   * This should be a unique identifier; either a string (present in `map`),
   * or a resolvable (via `require.resolve`) module ID/path.
   * @type {string}
   */
  const pluginId = opts[pluginType];

  if (Array.isArray(pluginId)) {
    throw createInvalidLegacyPluginError(
      `"--${pluginType}" can only be specified once`,
      pluginType,
    );
  }

  const createUnknownError = (err) =>
    createInvalidLegacyPluginError(
      format('Could not load %s "%s":\n\n %O', pluginType, pluginId, err),
      pluginType,
      pluginId,
    );

  // if this exists, then it's already loaded, so nothing more to do.
  if (!map[pluginId]) {
    let foundId;
    try {
      foundId = require.resolve(pluginId);
      map[pluginId] = require(foundId);

View on GitHub (pinned to 6bcbee4fd9)

Solutions

  1. Specify --reporter / --ui exactly once on the command line.
  2. If you merged configs, ensure `reporter`/`ui` are single strings, not arrays.
  3. Check npm scripts/CI wrappers for a second injected --reporter flag (e.g. coverage tools adding one) and deduplicate.
  4. For programmatic use, pass a string for reporter/ui in the Mocha constructor options.

Example fix

// before
mocha --reporter spec --reporter dot
// after
mocha --reporter dot
Defensive patterns

Strategy: validation

Validate before calling

function assertSingleFlag(flagName, values) {
  if (Array.isArray(values) || values.length > 1) {
    throw new Error(`--${flagName} can only be specified once`);
  }
}
assertSingleFlag('reporter', process.argv.filter(a => a === '--reporter'));

Type guard

function isSinglePluginId(v) {
  return typeof v === 'string'; // arrays mean the flag was duplicated/merged
}

Try / catch

try {
  await runMochaCLI(argv);
} catch (err) {
  if (err.code === 'ERR_MOCHA_INVALID_REPORTER' || err.code === 'ERR_MOCHA_INVALID_INTERFACE') {
    console.error('Deduplicate --reporter/--ui flags in your script/config');
  }
}

Prevention

When it happens

Trigger: Running `mocha --reporter spec --reporter dot` or `mocha --ui bdd --ui tdd`; programmatically passing an array as opts.reporter or opts.ui into validatePlugin/run; a merged config (CLI + mocharc) where both sources set the same flag and the merge produced an array.

Common situations: Shell scripts or npm scripts appending extra --reporter flags; combining a mocharc `reporter` array with CLI flags; typos where a list (e.g. comma-separated intent) was passed as repeated flags.

Related errors


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