mochajs/mocha · error · TypeError

ERR_MOCHA_INVALID_ARG_TYPE

ERR_MOCHA_INVALID_ARG_TYPE

Error message

Test argument "title" should be a string. Received type "${typeof title}"

What it means

The Test constructor requires its first argument `title` to be a string; any other type throws ERR_MOCHA_INVALID_ARG_TYPE. This is an eager input validation so misconstructed tests fail loudly at construction rather than producing cryptic errors later during the run.

Source

Thrown at lib/test.js:19

import { Runnable } from "./runnable.js";
import utils from "./utils.cjs";
import { createInvalidArgumentTypeError } from "./errors.js";

const { isString } = utils;
const { MOCHA_ID_PROP_NAME } = utils.constants;

class Test extends Runnable {
  /**
   * Initialize a new `Test` with the given `title` and callback `fn`.
   *
   * @public
   * @extends Runnable
   * @param {String} title - Test title (required)
   * @param {Function} [fn] - Test callback.  If omitted, the Test is considered "pending"
   */
  constructor(title, fn) {
    if (!isString(title)) {
      throw createInvalidArgumentTypeError(
        'Test argument "title" should be a string. Received type "' +
          typeof title +
          '"',
        "title",
        "string",
      );
    }
    super(title, fn);
    this.type = "test";
    this.reset();
  }

  /**
   * Resets the state initially or for a next run.
   */
  reset() {
    super.reset();
    this.pending = !this.fn;

View on GitHub (pinned to 6bcbee4fd9)

Solutions

  1. Pass a string title, e.g. new Test(String(name), fn) or `new Test(\`case ${i}\`, fn)`.
  2. Validate/coerce dynamic titles before constructing: skip entries with missing titles or stringify them.
  3. Check helpers/wrappers around `it()` that may drop or misplace the title argument.
  4. For data-driven tests, filter out records whose label is not a string before mapping to Tests.

Example fix

// before
items.forEach((item, i) => it(item.name, () => run(item))); // item.name undefined
// after
items.filter((item) => typeof item.name === 'string').forEach((item) => it(item.name, () => run(item)));
Defensive patterns

Strategy: type-guard

Validate before calling

function safeTest(title, fn) {
  if (typeof title !== 'string') throw new TypeError(`Test title must be a string, got ${typeof title}`);
  return new Test(title, fn);
}

Type guard

function isTestTitle(v) {
  return typeof v === 'string';
}
// usage: items.filter(i => isTestTitle(i.name)).forEach(i => it(i.name, ...))

Try / catch

try {
  tests.push(new Test(rawTitle, fn));
} catch (err) {
  if (err.code === 'ERR_MOCHA_INVALID_ARG_TYPE') {
    console.error(`Skipping test with invalid title: ${String(rawTitle)}`);
  }
}

Prevention

When it happens

Trigger: Calling new Test(123), new Test(undefined, fn) (e.g. from a helper generating tests), or passing a non-string title programmatically — including Test.extend or it()/specify() wrappers that forward titles.

Common situations: Dynamically generating tests from data where a key is undefined/null; array index used as title (number); template helper returning a non-string; copying example code that passed an object.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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