vitest-dev/vitest · error · SyntaxError

expect.poll() is not supported in combination with .

Error message

expect.poll() is not supported in combination with .${key}(). Use vi.waitFor() if your assertion condition is unstable.

What it means

expect.poll() retries an assertion until it passes or times out. Certain matchers are incompatible with retry semantics: snapshot matchers (always succeed once the value doesn't throw) and throw matchers (the poll callback is called until it stops throwing, so testing for throws is meaningless). The `unsupported` list blocks these combinations with a SyntaxError and points to vi.waitFor as the alternative for unstable non-assertion conditions.

Solutions

  1. For unstable snapshot conditions, use vi.waitFor(() => { expect(value).toMatchInlineSnapshot(...) }) instead.
  2. For throw-based conditions, restructure to poll the state directly rather than asserting a throw.
  3. Remove .poll() if the matcher doesn't need retry semantics.

Example fix

// before — unsupported combination:
await expect.poll(() => getValue()).toThrow()

// after — use vi.waitFor for unstable conditions:
await vi.waitFor(() => { expect(() => getValue()).toThrow() })
Defensive patterns

Strategy: validation

Validate before calling

const UNSUPPORTED_WITH_POLL = [
  'matchSnapshot','toMatchSnapshot','toMatchInlineSnapshot',
  'toThrowErrorMatchingSnapshot','toThrowErrorMatchingInlineSnapshot',
  'throws','Throw','throw','toThrow','toThrowError'
]
if (UNSUPPORTED_WITH_POLL.includes(matcherName)) {
  // use vi.waitFor instead of expect.poll
}

Prevention

When it happens

Trigger: Chaining .poll() with toMatchSnapshot, toMatchInlineSnapshot, matchSnapshot, toThrowErrorMatchingSnapshot, toThrowErrorMatchingInlineSnapshot, throws, Throw, throw, toThrow, or toThrowError. Any of these in `expect.poll(fn).X()` triggers the error.

Common situations: Trying to retry a snapshot assertion on an unstable value; attempting to poll until a function throws; copy-pasting an existing throw/snapshot assertion and adding .poll().

Related errors


AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11). Data as JSON: /api/errors/f6faef0c0793d8dc. Report an issue: GitHub.

Appendix: 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 1fa9837ec2)