vitest-dev/vitest · error · SyntaxError
expect.poll() is not supported in combination with .${key}()
Error message
expect.poll() is not supported in combination with .${key}(). Use vi.waitFor() if your assertion condition is unstable. What it means
`.poll` retries a matcher until it passes within a timeout, but several matchers are semantically incompatible with retrying: snapshot matchers would always pass once the poll callback doesn't throw, and `toThrow`-style matchers can never succeed because poll keeps invoking the callback until it stops throwing. Vitest blocks these combinations with a `SyntaxError` and points to `vi.waitFor()` for unstable non-assertion conditions.
Source
Thrown at packages/vitest/src/integrations/chai/poll.ts:82
chai.util.flag(assertion, '_poll.interval', interval)
const test = chai.util.flag(assertion, 'vitest-test') as Test | undefined
if (!test) {
throw new Error('expect.poll() must be called inside a test')
}
const proxy: any = new Proxy(assertion, {
get(target, key, receiver) {
const assertionFunction = Reflect.get(target, key, receiver)
if (typeof assertionFunction !== 'function') {
return assertionFunction instanceof chai.Assertion ? proxy : assertionFunction
}
if (key === 'assert') {
return assertionFunction
}
if (typeof key === 'string' && unsupported.includes(key)) {
throw new SyntaxError(
`expect.poll() is not supported in combination with .${key}(). Use vi.waitFor() if your assertion condition is unstable.`,
)
}
// Core poll stack-trace trick:
// 1. capture STACK_TRACE_ERROR here before entering the async poll loop
// 2. when the matcher eventually fails, rethrow via throwWithCause()
// so the final error keeps this earlier stack
//
// For example, when user writes:
// await expect.poll(...).toBeSomething()
// STACK_TRACE_ERROR.stack would look like
// at ...(more internal stacks)...
// at __VITEST_POLL_CHAIN__ .../packages/vitest/dist/...
// at .../my-file.test.ts:12:3 (this points to `toBeSomething()` callsite in user test file)
// Vitest later filters out internal stacks from `vitest/dist`, so the reported errors correctly
// points to the user callsite for poll assertion errors.
//View on GitHub (pinned to d568f8ce37)
Solutions
- For eventual-value assertions, poll on a stable matcher (`.toBe`, `.toEqual`, etc.) and call `toMatchSnapshot` separately after the value resolves.
- For an unstable condition that is not an assertion, use `vi.waitFor(() => condition)` or `vi.waitUntil(() => condition)`.
- For eventual throw behavior, await the action inside poll and assert the resolved/thrown value with a non-throw matcher.
Example fix
// before await expect.poll(() => readVal()).toMatchSnapshot() // after const val = await vi.waitFor(() => readVal()) expect(val).toMatchSnapshot()
Defensive patterns
Strategy: validation
Validate before calling
const unsupported = ['matchSnapshot','toMatchSnapshot','toMatchInlineSnapshot','toThrowErrorMatchingSnapshot','toThrowErrorMatchingInlineSnapshot','throws','Throw','throw','toThrow','toThrowError'] // review your poll chains: never append a name from `unsupported`
Prevention
- After `expect.poll(...)`, only use stable value matchers (`.toBe`, `.toEqual`, ...).
- Resolve the value with `vi.waitFor` first, then snapshot it separately.
When it happens
Trigger: Chaining any of: `matchSnapshot`, `toMatchSnapshot`, `toMatchInlineSnapshot`, `toThrowErrorMatchingSnapshot`, `toThrowErrorMatchingInlineSnapshot`, `throws`, `Throw`, `throw`, `toThrow`, `toThrowError` after `expect.poll(...)`, e.g. `await expect.poll(fn).toMatchSnapshot()`.
Common situations: Migrating a flaky snapshot test to poll, or trying to assert that something eventually throws by combining poll with `.toThrow()`.
Related errors
- '${getAssertionName(obj)}' cannot be used with 'test.fails'
- ${getAssertionName(assertion)} cannot be used with "not"
- .toContainHTML() expects a string value, got ${htmlText}
- Exact option does not support RegExp expected class names
- .toHaveDisplayValue() currently supports only input, textare
AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03).
Data as JSON: /data/errors/f6faef0c0793d8dc.json.
Report an issue: GitHub.