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
- Specify --reporter / --ui exactly once on the command line.
- If you merged configs, ensure `reporter`/`ui` are single strings, not arrays.
- Check npm scripts/CI wrappers for a second injected --reporter flag (e.g. coverage tools adding one) and deduplicate.
- 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
- Pass --reporter/--ui at most once per invocation
- Check npm/CI scripts for wrappers injecting a second reporter flag
- Keep mocharc reporter/ui values as single strings, not arrays
- Deduplicate merged option objects before programmatic runs
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
- Not enough non-option arguments: got 0, need at least 1
- Not enough arguments following: ${name}
- Warning: ${warning.message}
- ERR_MOCHA_NO_FILES_MATCH_PATTERN
- ERR_MOCHA_INVALID_ARG_TYPE
AI-assisted analysis of mochajs/mocha@6bcbee4fd9 (2026-09-01).
Data as JSON: /api/errors/ffb611bd398c8314.
Report an issue: GitHub.