{"record":{"id":"b7121db09b2c08f7","repo":"vitest-dev/vitest","slug":"snapshot-function-didn-t-throw","errorCode":null,"errorMessage":"snapshot function didn't throw","messagePattern":"snapshot function didn't throw","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/integrations/snapshot/chai.ts","lineNumber":46,"sourceCode":"  if (typeof expected !== 'function') {\n    if (!promise) {\n      throw new Error(\n        `expected must be a function, received ${typeof expected}`,\n      )\n    }\n\n    // when \"promised\", it receives thrown error\n    return expected\n  }\n\n  try {\n    expected()\n  }\n  catch (e) {\n    return e\n  }\n\n  throw new Error('snapshot function didn\\'t throw')\n}\n\nfunction getTestNames(test: Test) {\n  return {\n    filepath: test.file.filepath,\n    name: getNames(test).slice(1).join(' > '),\n    testId: test.id,\n  }\n}\n\nfunction getAssertionName(assertion: Chai.Assertion): string {\n  const name = chai.util.flag(assertion, '_name') as string | undefined\n  if (!name) {\n    throw new Error('Assertion name is not set. This is a bug in Vitest. Please, open a new issue with reproduction.')\n  }\n  return name\n}\n","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/vitest-dev/vitest/blob/1fa9837ec26533512fdcad8baebf249771bd340a/packages/vitest/src/integrations/snapshot/chai.ts#L28-L64","documentation":"Thrown by `getError` after it successfully invoked the `expected` function but the function returned without throwing. The snapshot-matching assertions for thrown errors require that the wrapped code actually throws an error to snapshot; if nothing is thrown, there is no error to capture and the assertion fails with this message.","triggerScenarios":"Calling `expect(() => { /* nothing */ }).toThrowErrorMatchingSnapshot()` when the function body does not throw; the code path under test was refactored to no longer throw; conditional throw that wasn't triggered by the test inputs.","commonSituations":"Test written before the throwing branch existed; mock swallowing the throw; logic change that returns instead of throwing; data-dependent throw where the test data doesn't hit the throw path.","solutions":["Verify the function actually throws under the test's inputs (add a direct `toThrow()` check first).","Update the test data/conditions so the throwing branch is exercised.","If the behavior intentionally no longer throws, remove the snapshot assertion."],"exampleFix":"// before\nfunction safe(x) { return x }\nexpect(() => safe(1)).toThrowErrorMatchingSnapshot()\n\n// after (assume the real throwing branch)\nfunction risky(x) { if (x < 0) throw new Error('negative') }\nexpect(() => risky(-1)).toThrowErrorMatchingSnapshot()","handlingStrategy":"validation","validationCode":"function expectThrows(fn) {\n  let threw = false\n  try { fn() } catch { threw = true }\n  if (!threw) throw new Error('setup error: function did not throw')\n  expect(fn).toThrowErrorMatchingSnapshot()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Confirm the function throws under the test inputs before snapshotting.","Use test data that exercises the throwing branch.","Re-snapshot assertions whenever the error message or shape changes."],"tags":["snapshot","tothrowerrormatchingsnapshot","assertion-failure"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}