{"id":"82e8e13ea496a564","repo":"jestjs/jest","slug":"received-value-must-be-a-function","errorCode":null,"errorMessage":"received value must be a function","messagePattern":"received value must be a function","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/expect/src/toThrowMatchers.ts","lineNumber":102,"sourceCode":"      isNot: this.isNot,\n      promise: this.promise,\n    };\n\n    let thrown = null;\n\n    if (fromPromise && isError(received)) {\n      thrown = getThrown(received);\n    } else {\n      if (typeof received === 'function') {\n        try {\n          received();\n        } catch (error) {\n          thrown = getThrown(error);\n        }\n      } else {\n        if (!fromPromise) {\n          const placeholder = expected === undefined ? '' : 'expected';\n          throw new Error(\n            matcherErrorMessage(\n              matcherHint(matcherName, undefined, placeholder, options),\n              `${RECEIVED_COLOR('received')} value must be a function`,\n              printWithType('Received', received, printReceived),\n            ),\n          );\n        }\n      }\n    }\n\n    if (expected === undefined) {\n      return toThrow(matcherName, options, thrown);\n    } else if (typeof expected === 'function') {\n      return toThrowExpectedClass(matcherName, options, thrown, expected);\n    } else if (typeof expected === 'string') {\n      return toThrowExpectedString(matcherName, options, thrown, expected);\n    } else if (expected !== null && typeof expected.test === 'function') {\n      return toThrowExpectedRegExp(matcherName, options, thrown, expected);","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/jestjs/jest/blob/f49721c78e195558b40913977c9230f5b7f559d8/packages/expect/src/toThrowMatchers.ts#L84-L120","documentation":"Thrown by `toThrow` / `toThrowError` (toThrowMatchers.ts:78, via `createMatcher`) when the value passed to `expect(...)` is not a function and the matcher was not invoked through `.rejects` (the `fromPromise` path). `toThrow` works by calling `received()` inside a try/catch to capture the thrown error; a non-function received cannot be invoked. The check is gated by `!fromPromise`, so `expect(promise).rejects.toThrow()` does not hit this — only the synchronous misuse does.","triggerScenarios":"Calling `expect(value).toThrow()` where `value` is a string, number, object, undefined, null, or the result of calling a function (instead of the function reference itself). Common: `expect(fn()).toThrow()` — the parens invoke `fn` before `toThrow` can wrap it, so `received` is the return value, not the function. Also `expect(asyncFn()).toThrow()` on a non-awaited async call (should use `.rejects.toThrow()`).","commonSituations":"Adding parentheses by accident (`expect(fn())` instead of `expect(fn)`); forgetting `.rejects` for async-rejection assertions; passing an error instance directly instead of a throwing function; refactoring from a try/catch test style.","solutions":["Pass the function reference, not its result: `expect(fn).toThrow()` (no parens on `fn`).","For async rejections, use `expect(promise).rejects.toThrow()`.","Wrap an inline expression in an arrow function: `expect(() => parse(bad)).toThrow()`.","If you already have the error, assert on it directly with `expect(err.message).toBe(...)` rather than `toThrow`."],"exampleFix":"// before\nexpect(validate(input)).toThrow(); // validate runs before toThrow\n\n// after\nexpect(() => validate(input)).toThrow();","handlingStrategy":"type-guard","validationCode":"if (typeof received !== 'function') {\n  throw new Error(`received must be a function for toThrow, got ${typeof received}`);\n}\nexpect(received).toThrow();","typeGuard":"const isFunction = (v: unknown): v is (...args: any[]) => any =>\n  typeof v === 'function';","tryCatchPattern":"try {\n  expect(received).toThrow();\n} catch (e) {\n  if (e instanceof Error && /received value must be a function/.test(e.message)) {\n    console.error('pass the function reference, not its result (drop the parens)');\n  }\n  throw e;\n}","preventionTips":["Pass the function reference: `expect(fn).toThrow()`, never `expect(fn()).toThrow()`.","Wrap inline expressions: `expect(() => parse(bad)).toThrow()`.","For async rejections, use `expect(promise).rejects.toThrow()`."],"tags":["jest","expect","type-validation","assertion","error-handling","async"],"analyzedSha":"f49721c78e195558b40913977c9230f5b7f559d8","analyzedAt":"2026-08-03T20:16:28.571Z","schemaVersion":2}