{"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":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/jest-jasmine2/src/jasmine/Env.ts","lineNumber":560,"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":542,"sourceCodeEnd":578,"githubUrl":"https://github.com/jestjs/jest/blob/f49721c78e195558b40913977c9230f5b7f559d8/packages/jest-jasmine2/src/jasmine/Env.ts#L542-L578","documentation":"it()/test()'s second argument must be a function. Env.ts:559-562 throws a TypeError when fn is defined but not a function (e.g. an object, array, config, or value). The interpolated fn in the message shows exactly what was passed.","triggerScenarios":"Calling `it('name', { skip: true })`, `it('name', 42)`, or otherwise passing a non-function. The `typeof fn !== 'function'` check at Env.ts:559 fires the TypeError at line 560.","commonSituations":"Passing an options object meant for a custom wrapper; destructuring bug forwarding the wrong value; refactoring a parametrized test incorrectly.","solutions":["Pass a function: it('name', () => { ... }).","Use the interpolated value in the error to identify the wrong binding and fix it.","For options like timeout, pass them as the third argument: it('name', fn, 1000)."],"exampleFix":"// before — options object passed as body\nit('calculates tax', { timeout: 1000 });\n\n// after — function body, timeout as 3rd arg\nit('calculates tax', () => { expect(calc(10)).toBe(1); }, 1000);","handlingStrategy":"type-guard","validationCode":"function assertItFn(fn: unknown) {\n  if (typeof fn !== 'function') throw new TypeError('it callback must be a function');\n}","typeGuard":"function isFn(v: unknown): v is Function { return typeof v === 'function'; }\nif (!isFn(fn)) throw new TypeError('it needs a function callback');","tryCatchPattern":null,"preventionTips":["Pass options like timeout as the 3rd argument, never as the 2nd.","Type test helpers so a non-function it body is a compile error."],"tags":["jasmine2","it","test","api-misuse","typeerror","test-structure"],"analyzedSha":"f49721c78e195558b40913977c9230f5b7f559d8","analyzedAt":"2026-08-03T20:16:28.571Z","schemaVersion":2}