vitest-dev/vitest · error · TestSyntaxError
'${getAssertionName(obj)}' cannot be used with 'test.fails'
Error message
'${getAssertionName(obj)}' cannot be used with 'test.fails' What it means
`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.
Source
Thrown at packages/vitest/src/integrations/snapshot/chai.ts:71
testId: test.id,
}
}
function getAssertionName(assertion: Chai.Assertion): string {
const name = chai.util.flag(assertion, '_name') as string | undefined
if (!name) {
throw new Error('Assertion name is not set. This is a bug in Vitest. Please, open a new issue with reproduction.')
}
return name
}
function getTest(obj: Chai.Assertion) {
const test = chai.util.flag(obj, 'vitest-test') as Test | undefined
if (!test) {
throw new Error(`'${getAssertionName(obj)}' cannot be used without test context`)
}
if (test.fails) {
throw new TestSyntaxError(`'${getAssertionName(obj)}' cannot be used with 'test.fails'`)
}
return test
}
function validateAssertion(assertion: Chai.Assertion): void {
if (chai.util.flag(assertion, 'negate')) {
throw new Error(`${getAssertionName(assertion)} cannot be used with "not"`)
}
}
export const SnapshotPlugin: ChaiPlugin = (chai, utils) => {
for (const key of ['matchSnapshot', 'toMatchSnapshot']) {
utils.addMethod(
chai.Assertion.prototype,
key,
wrapAssertion(utils, key, function (
this,
propertiesOrHint?: object | string,View on GitHub (pinned to d568f8ce37)
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.
Example fix
// before
test.fails('rejects invalid', () => {
expect(parse('bad')).toMatchSnapshot()
})
// after
test('rejects invalid', () => {
expect(() => parse('bad')).toThrow(/invalid/)
}) Defensive patterns
Strategy: validation
Validate before calling
// do not combine test.fails with writing snapshot matchers // if you need to snapshot, use a regular test()
Prevention
- Never use `test.fails` with snapshot matchers; assert failures explicitly instead.
- Split failing-path assertions and snapshot assertions into separate tests.
When it happens
Trigger: Placing `expect(...).toMatchSnapshot()` / `.toMatchInlineSnapshot()` / `.toMatchFileSnapshot()` / `toThrowErrorMatching*Snapshot()` inside a `test.fails('...', () => { ... })` callback.
Common situations: Marking an error-path test with `test.fails` while also snapshotting, or converting a passing snapshot test to `test.fails` during debugging.
Related errors
- expect.poll() is not supported in combination with .${key}()
- ${getAssertionName(assertion)} cannot be used with "not"
- expected must be a function, received ${typeof expected}
- snapshot function didn't throw
- '${getAssertionName(obj)}' cannot be used without test conte
AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03).
Data as JSON: /data/errors/6200820fd53b1165.json.
Report an issue: GitHub.