jestjs/jest · error · TypeError

Invalid second argument

Error message

Invalid second argument, ${fn}. It must be a callback function.

What it means

it/test requires its second argument to be a function. If a defined but non-function value is passed (string, number, object, array), Env.it throws a TypeError at Env.ts:568 naming the offending value. This distinguishes 'no argument' (use todo) from 'wrong-typed argument'.

Solutions

  1. Pass a function as the second argument: `it('x', () => {})`.
  2. If you need a timeout, it is the THIRD argument: `it('x', () => {}, 5000)`.
  3. Verify the type of any variable passed as fn before the call.

Example fix

// before
it('slow test', 10000);
// after
it('slow test', () => { /* ... */ }, 10000);
Defensive patterns

Strategy: type-guard

Validate before calling

function safeIt(name: string, fn: unknown, timeout?: number) {
  if (typeof fn !== 'function') {
    throw new TypeError(`it('${name}') requires a function callback, got ${typeof fn}.`);
  }
  return it(name, fn, timeout);
}

Type guard

function isTestFn(value: unknown): value is () => void | Promise<void> {
  return typeof value === 'function';
}

Prevention

When it happens

Trigger: Calling `it('x', 123)`, `it('x', 'body')`, or `it('x', { timeout: 5000 })`. The guard at Env.ts:567 checks `typeof fn !== 'function'`.

Common situations: Passing a timeout as the second arg by mistake (should be third); passing an options object instead of a callback; a helper returning a non-function; copy-paste from jest-each where the table was the first arg and the callback was dropped.

Related errors


AI-assisted analysis of jestjs/jest@8e6d128e4a (2026-08-10). Data as JSON: /api/errors/30c29fee3aded893. Report an issue: GitHub.

Appendix: source

Thrown at packages/jest-jasmine2/src/jasmine/Env.ts:568

          reporter.specDone(result);
        }

        function specStarted(spec: Spec) {
          currentSpec = spec;
          defaultResourcesForRunnable(spec.id, suite.id);
          reporter.specStarted(spec.result);
        }
      };

      this.it = function (description, fn, timeout) {
        description = convertDescriptorToString(description);
        if (fn === undefined) {
          throw new Error(
            'Missing second argument. It must be a callback function. Perhaps you want to use `test.todo` for a test placeholder.',
          );
        }
        if (typeof fn !== 'function') {
          throw new TypeError(
            `Invalid second argument, ${fn}. It must be a callback function.`,
          );
        }
        const spec = specFactory(
          description,
          fn,
          currentDeclarationSuite,
          timeout,
        );
        if (currentDeclarationSuite.markedPending) {
          spec.pend();
        }

        // When a test is defined inside another, jasmine will not run it.
        // This check throws an error to warn the user about the edge-case.
        if (currentSpec !== null) {
          throw new Error(
            `Tests cannot be nested. Test "${spec.description}" cannot run because it is nested within "${currentSpec.description}".`,

View on GitHub (pinned to 8e6d128e4a)