{"id":"f6faef0c0793d8dc","repo":"vitest-dev/vitest","slug":"expect-poll-is-not-supported-in-combination-with-f6faef","errorCode":null,"errorMessage":"expect.poll() is not supported in combination with .${key}(). Use vi.waitFor() if your assertion condition is unstable.","messagePattern":"expect\\.poll\\(\\) is not supported in combination with \\.(.+?)\\(\\)\\. Use vi\\.waitFor\\(\\) if your assertion condition is unstable\\.","errorType":"exception","errorClass":"SyntaxError","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/integrations/chai/poll.ts","lineNumber":82,"sourceCode":"    chai.util.flag(assertion, '_poll.interval', interval)\n    const test = chai.util.flag(assertion, 'vitest-test') as Test | undefined\n    if (!test) {\n      throw new Error('expect.poll() must be called inside a test')\n    }\n    const proxy: any = new Proxy(assertion, {\n      get(target, key, receiver) {\n        const assertionFunction = Reflect.get(target, key, receiver)\n\n        if (typeof assertionFunction !== 'function') {\n          return assertionFunction instanceof chai.Assertion ? proxy : assertionFunction\n        }\n\n        if (key === 'assert') {\n          return assertionFunction\n        }\n\n        if (typeof key === 'string' && unsupported.includes(key)) {\n          throw new SyntaxError(\n            `expect.poll() is not supported in combination with .${key}(). Use vi.waitFor() if your assertion condition is unstable.`,\n          )\n        }\n\n        // Core poll stack-trace trick:\n        //   1. capture STACK_TRACE_ERROR here before entering the async poll loop\n        //   2. when the matcher eventually fails, rethrow via throwWithCause()\n        //      so the final error keeps this earlier stack\n        //\n        // For example, when user writes:\n        //    await expect.poll(...).toBeSomething()\n        // STACK_TRACE_ERROR.stack would look like\n        //   at ...(more internal stacks)...\n        //   at __VITEST_POLL_CHAIN__ .../packages/vitest/dist/...\n        //   at .../my-file.test.ts:12:3   (this points to `toBeSomething()` callsite in user test file)\n        // Vitest later filters out internal stacks from `vitest/dist`, so the reported errors correctly\n        // points to the user callsite for poll assertion errors.\n        //","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/vitest/src/integrations/chai/poll.ts#L64-L100","documentation":"`.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.","triggerScenarios":"Chaining any of: `matchSnapshot`, `toMatchSnapshot`, `toMatchInlineSnapshot`, `toThrowErrorMatchingSnapshot`, `toThrowErrorMatchingInlineSnapshot`, `throws`, `Throw`, `throw`, `toThrow`, `toThrowError` after `expect.poll(...)`, e.g. `await expect.poll(fn).toMatchSnapshot()`.","commonSituations":"Migrating a flaky snapshot test to poll, or trying to assert that something eventually throws by combining poll with `.toThrow()`.","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."],"exampleFix":"// before\nawait expect.poll(() => readVal()).toMatchSnapshot()\n// after\nconst val = await vi.waitFor(() => readVal())\nexpect(val).toMatchSnapshot()","handlingStrategy":"validation","validationCode":"const unsupported = ['matchSnapshot','toMatchSnapshot','toMatchInlineSnapshot','toThrowErrorMatchingSnapshot','toThrowErrorMatchingInlineSnapshot','throws','Throw','throw','toThrow','toThrowError']\n// review your poll chains: never append a name from `unsupported`","typeGuard":null,"tryCatchPattern":null,"preventionTips":["After `expect.poll(...)`, only use stable value matchers (`.toBe`, `.toEqual`, ...).","Resolve the value with `vi.waitFor` first, then snapshot it separately."],"tags":["expect","poll","snapshot","syntax","matcher"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}