jestjs/jest · error · Error

Missing second argument. It must be a callback function…

Error message

Missing second argument. It must be a callback function. Perhaps you want to use `test.todo` for a test placeholder.

What it means

The `it()`/`test()` function requires a callback as its second argument. If `fn` is undefined (only the description was passed, or the second arg was explicitly omitted), Env.it throws this Error at Env.ts:563. The message specifically suggests `test.todo` because a common intent behind a no-callback test is a placeholder.

Solutions

  1. Add the callback: `it('does a thing', () => { expect(...).toBe(...) })`.
  2. If you want a placeholder, use `test.todo('does a thing')` instead of `it(...)` with no body.
  3. If you want to skip temporarily, use `it.skip('...', () => {})`.

Example fix

// before
it('will test the API');
// after — either add a body or use todo
it('will test the API', () => { /* ... */ });
// or
test.todo('will test the API');
Defensive patterns

Strategy: type-guard

Validate before calling

// Normalize: if no callback, convert to test.todo.
function safeIt(name: string, fn?: () => void | Promise<void>, timeout?: number) {
  if (fn === undefined) return it.todo(name);
  return it(name, fn, timeout);
}

Type guard

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

Prevention

When it happens

Trigger: Calling `it('does a thing')` with no callback, or `test('pending')`. The guard at Env.ts:562 checks `fn === undefined`.

Common situations: Writing a test stub/intention and forgetting the body; intending a todo but using `it` instead of `it.todo`/`test.todo`; a refactor that removed the callback but left the title.

Related errors


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

Appendix: source

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

        return spec;

        function specResultCallback(result: SpecResult) {
          clearResourcesForRunnable(spec.id);
          currentSpec = null;
          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();
        }

View on GitHub (pinned to 8e6d128e4a)