{"record":{"id":"e66aa44ae3212e36","repo":"vitest-dev/vitest","slug":"expected-promise-to-throw-an-error-but-it-didn-t","errorCode":null,"errorMessage":"expected promise to throw an error, but it didn't","messagePattern":"expected promise to throw an error, but it didn't","errorType":"exception","errorClass":"AssertionError","httpStatus":null,"severity":"error","filePath":"packages/expect/src/jest-expect.ts","lineNumber":90,"sourceCode":"        const object = utils.flag(this, 'object')\n        const isNot = utils.flag(this, 'negate') as boolean\n        if (promise === 'rejects') {\n          utils.flag(this, 'object', () => {\n            throw object\n          })\n        }\n        // if it got here, it's already resolved\n        // unless it tries to resolve to a function that should throw\n        // called as '.resolves[.not].toThrow()`\n        else if (promise === 'resolves' && typeof object !== 'function') {\n          if (!isNot) {\n            const message\n              = utils.flag(this, 'message')\n                || 'expected promise 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          else {\n            return\n          }\n        }\n        _super.apply(this, args)\n      }\n    })\n  })\n\n  // @ts-expect-error @internal\n  def('withTest', function (test: Test) {\n    utils.flag(this, 'vitest-test', test)\n    return this\n  })\n\n  def('toEqual', function (expected) {\n    const actual = utils.flag(this, 'object')","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/vitest-dev/vitest/blob/1fa9837ec26533512fdcad8baebf249771bd340a/packages/expect/src/jest-expect.ts#L72-L108","documentation":"Thrown in the toThrow/throws/Throw overwrite when the assertion is in 'resolves' mode (expect(p).resolves.toThrow()), the awaited value is not a function, and the assertion is not negated. It means: the promise resolved successfully to a non-throwing value, so there was nothing to throw.","triggerScenarios":"await expect(promise).resolves.toThrow() where the promise resolves to a plain value (not a function) and .not is not present. The resolves branch expects a function that throws when called; a resolved value has nothing to invoke.","commonSituations":"Confusing resolves.toThrow with rejects.toThrow — wanting the promise to reject, not the resolved value to throw; calling toThrow on a promise that resolves to data expecting it to validate errors.","solutions":["Use await expect(promise).rejects.toThrow() when you expect the promise itself to reject.","If the promise resolves to a function and you want that function's throw, ensure the resolved value is actually a function.","Re-check the assertion intent — most often .rejects is what was meant."],"exampleFix":"// before\nawait expect(fetchUser()).resolves.toThrow()\n// after\nawait expect(fetchUser()).rejects.toThrow('not found')","handlingStrategy":"validation","validationCode":"// Clarify intent before writing the assertion.\nfunction expectRejection(promise) {\n  return expect(promise).rejects\n}\n// then: await expectRejection(fetchUser()).toThrow('not found')","typeGuard":null,"tryCatchPattern":"try {\n  await expect(promise).resolves.toThrow()\n} catch (e) {\n  if (/expected promise to throw/.test(String(e?.message))) {\n    // likely meant .rejects — retry against rejection\n    await expect(promise).rejects.toThrow()\n    return\n  }\n  throw e\n}","preventionTips":["Use .rejects.toThrow() to assert a promise rejects; .resolves.toThrow() only fits promises that resolve to a throwing function.","Double-check the resolved value type before chaining .resolves.toThrow.","Prefer await expect(...).rejects to await expect(...).resolves.toThrow unless you intentionally return a function."],"tags":["expect","async","promise","matcher"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}