{"record":{"id":"30c29fee3aded893","repo":"jestjs/jest","slug":"invalid-second-argument-fn-it-must-be-a-callb","errorCode":null,"errorMessage":"Invalid second argument, ${fn}. It must be a callback function.","messagePattern":"Invalid second argument, (.+?)\\. It must be a callback function\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/jest-jasmine2/src/jasmine/Env.ts","lineNumber":568,"sourceCode":"          reporter.specDone(result);\n        }\n\n        function specStarted(spec: Spec) {\n          currentSpec = spec;\n          defaultResourcesForRunnable(spec.id, suite.id);\n          reporter.specStarted(spec.result);\n        }\n      };\n\n      this.it = function (description, fn, timeout) {\n        description = convertDescriptorToString(description);\n        if (fn === undefined) {\n          throw new Error(\n            'Missing second argument. It must be a callback function. Perhaps you want to use `test.todo` for a test placeholder.',\n          );\n        }\n        if (typeof fn !== 'function') {\n          throw new TypeError(\n            `Invalid second argument, ${fn}. It must be a callback function.`,\n          );\n        }\n        const spec = specFactory(\n          description,\n          fn,\n          currentDeclarationSuite,\n          timeout,\n        );\n        if (currentDeclarationSuite.markedPending) {\n          spec.pend();\n        }\n\n        // When a test is defined inside another, jasmine will not run it.\n        // This check throws an error to warn the user about the edge-case.\n        if (currentSpec !== null) {\n          throw new Error(\n            `Tests cannot be nested. Test \"${spec.description}\" cannot run because it is nested within \"${currentSpec.description}\".`,","sourceCodeStart":550,"sourceCodeEnd":586,"githubUrl":"https://github.com/jestjs/jest/blob/8e6d128e4a278059ecddecaa97400b04c8ae5fd9/packages/jest-jasmine2/src/jasmine/Env.ts#L550-L586","documentation":"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'.","triggerScenarios":"Calling `it('x', 123)`, `it('x', 'body')`, or `it('x', { timeout: 5000 })`. The guard at Env.ts:567 checks `typeof fn !== 'function'`.","commonSituations":"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.","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."],"exampleFix":"// before\nit('slow test', 10000);\n// after\nit('slow test', () => { /* ... */ }, 10000);","handlingStrategy":"type-guard","validationCode":"function safeIt(name: string, fn: unknown, timeout?: number) {\n  if (typeof fn !== 'function') {\n    throw new TypeError(`it('${name}') requires a function callback, got ${typeof fn}.`);\n  }\n  return it(name, fn, timeout);\n}","typeGuard":"function isTestFn(value: unknown): value is () => void | Promise<void> {\n  return typeof value === 'function';\n}","tryCatchPattern":null,"preventionTips":["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]."],"tags":["it","test","typeerror","api-misuse","jasmine","validation"],"backgroundTag":null,"analyzedSha":"8e6d128e4a278059ecddecaa97400b04c8ae5fd9","analyzedAt":"2026-08-10T18:11:27.960Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}