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
- Pass a function as the second argument: `it('x', () => {})`.
- If you need a timeout, it is the THIRD argument: `it('x', () => {}, 5000)`.
- 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
- Pass the function reference as the second argument; timeout is the third.
- Use TypeScript so the it() signature enforces the callback type.
- Double-check jest-each usage where the table is arg[0] and callback is arg[1].
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
- Missing second argument. It must be a callback function…
- Invalid first argument. It must be a callback function.
- Invalid second argument
- Todo must be called with only a description.
- Argument passed to callFake should be a function, got
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)