{"id":"c6d98b9e195d54d3","repo":"vitest-dev/vitest","slug":"expected-function-to-throw-an-error-but-it-didn-t","errorCode":null,"errorMessage":"expected function to throw an error, but it didn't","messagePattern":"expected function to throw an error, but it didn't","errorType":"exception","errorClass":"AssertionError","httpStatus":null,"severity":"error","filePath":"packages/expect/src/jest-expect.ts","lineNumber":797,"sourceCode":"      }\n      else {\n        let isThrow = false\n        try {\n          obj()\n        }\n        catch (err) {\n          isThrow = true\n          thrown = err\n        }\n\n        if (!isThrow && !isNot) {\n          const message\n            = utils.flag(this, 'message')\n              || 'expected function to throw an error, but it didn\\'t'\n          const error = {\n            showDiff: false,\n          }\n          throw new AssertionError(message, error, utils.flag(this, 'ssfi'))\n        }\n      }\n\n      if (typeof expected === 'function') {\n        const name = expected.name || expected.prototype.constructor.name\n        return this.assert(\n          thrown && thrown instanceof expected,\n          `expected error to be instance of ${name}`,\n          `expected error not to be instance of ${name}`,\n          expected,\n          thrown,\n        )\n      }\n\n      if (isError(expected)) {\n        const equal = jestEquals(thrown, expected, [\n          ...customTesters,\n          iterableEquality,","sourceCodeStart":779,"sourceCodeEnd":815,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/expect/src/jest-expect.ts#L779-L815","documentation":"AssertionError thrown by toThrow/toThrowError when the target function (obj) was invoked and did not throw, in the non-negated form. The matcher invokes obj() inside try/catch (line 782-788); if isThrow stays false and !isNot, it reports that no error was thrown.","triggerScenarios":"expect(fn).toThrow() where fn() returns normally without throwing. Equivalent to expect(fn).toThrow(undefined) or .toThrow('msg')/.toThrow(/re/) when no error is raised.","commonSituations":"The code under test does not actually throw on the given input — e.g. a validation function that returns false instead of throwing, an async function whose rejection was swallowed, or a conditional throw that was not triggered.","solutions":["Confirm the function actually throws under the test conditions (add a console.log or step through).","If the function returns an error instead of throwing, assert on the return value with toEqual/toMatchObject instead of toThrow.","If the throw is conditional, ensure the input satisfies the throwing branch."],"exampleFix":"// before\nexpect(() => validate('')).toThrow(ValidationError);\n// after (validate returns { error } instead)\nexpect(validate('')).toEqual({ error: expect.any(ValidationError) });","handlingStrategy":"validation","validationCode":"let threw = false;\ntry { fn(); } catch { threw = true; }\nif (!threw) throw new Error('fn did not throw under test conditions');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Confirm the throwing branch is reachable for the given input.","If the function returns an error rather than throwing, assert on the return value instead."],"tags":["assertion","tothrow","function","no-throw"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}