{"id":"6200820fd53b1165","repo":"vitest-dev/vitest","slug":"getassertionname-obj-cannot-be-used-with-te","errorCode":null,"errorMessage":"'${getAssertionName(obj)}' cannot be used with 'test.fails'","messagePattern":"'(.+?)' cannot be used with 'test\\.fails'","errorType":"exception","errorClass":"TestSyntaxError","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/integrations/snapshot/chai.ts","lineNumber":71,"sourceCode":"    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\nfunction getTest(obj: Chai.Assertion) {\n  const test = chai.util.flag(obj, 'vitest-test') as Test | undefined\n  if (!test) {\n    throw new Error(`'${getAssertionName(obj)}' cannot be used without test context`)\n  }\n  if (test.fails) {\n    throw new TestSyntaxError(`'${getAssertionName(obj)}' cannot be used with 'test.fails'`)\n  }\n  return test\n}\n\nfunction validateAssertion(assertion: Chai.Assertion): void {\n  if (chai.util.flag(assertion, 'negate')) {\n    throw new Error(`${getAssertionName(assertion)} cannot be used with \"not\"`)\n  }\n}\n\nexport const SnapshotPlugin: ChaiPlugin = (chai, utils) => {\n  for (const key of ['matchSnapshot', 'toMatchSnapshot']) {\n    utils.addMethod(\n      chai.Assertion.prototype,\n      key,\n      wrapAssertion(utils, key, function (\n        this,\n        propertiesOrHint?: object | string,","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/vitest/src/integrations/snapshot/chai.ts#L53-L89","documentation":"`getTest` rejects snapshot matchers inside a `test.fails(...)` block by throwing a `TestSyntaxError`. Snapshot matchers record their result into the snapshot file as a side effect; under `test.fails` the test is expected to fail, but a passing snapshot write would still mutate disk state, producing confusing semantics. Vitest forbids the combination outright.","triggerScenarios":"Placing `expect(...).toMatchSnapshot()` / `.toMatchInlineSnapshot()` / `.toMatchFileSnapshot()` / `toThrowErrorMatching*Snapshot()` inside a `test.fails('...', () => { ... })` callback.","commonSituations":"Marking an error-path test with `test.fails` while also snapshotting, or converting a passing snapshot test to `test.fails` during debugging.","solutions":["Remove `test.fails` and instead assert the expected failure explicitly (e.g. `expect(() => ...).toThrow(...)`).","Move the snapshot assertion into a separate non-`fails` test that documents the current/expected output.","If the test genuinely should fail, do not use a writing snapshot matcher there."],"exampleFix":"// before\ntest.fails('rejects invalid', () => {\n  expect(parse('bad')).toMatchSnapshot()\n})\n// after\ntest('rejects invalid', () => {\n  expect(() => parse('bad')).toThrow(/invalid/)\n})","handlingStrategy":"validation","validationCode":"// do not combine test.fails with writing snapshot matchers\n// if you need to snapshot, use a regular test()","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never use `test.fails` with snapshot matchers; assert failures explicitly instead.","Split failing-path assertions and snapshot assertions into separate tests."],"tags":["snapshot","test-fails","syntax","matcher"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}