Structural Comparison Matrix
| # | Change | Throws or silent? | Applies to you if… |
|---|---|---|---|
| 1 | vi.mock top-level scope enforcement | Throws | You call vi.mock/vi.unmock/vi.hoisted inside a describe/test block |
| 2 | clearMocks defaults to true | Silent | Any suite that asserts on mock call counts across multiple tests |
| 3 | test.sequential / describe.sequential removed | Throws (removed API) | You use either option instead of { concurrent: false } |
| 4 | Config not found in parent directory | Silent (CLI fails) | You run vitest from a subdirectory relying on a parent config |
| 5 | bench no longer a top-level export | Throws (removed API) | You use Vitest’s benchmarking API |
| 6 | Unawaited async assertions fail | Throws | Your suite has an expect(promise).resolves... without await |
| 7 | expect.poll rejects on timeout | Throws | You use expect.poll() to wait on an async condition |
| 8 | 8 subpath entry points removed | Throws (import error) | You import from vitest/reporters, vitest/coverage, etc. directly |
| 9 | toThrow('') matches any error | Silent | Any test asserting toThrow('') expecting an empty-message-only match |
| 10 | Inline projects inherit root config | Silent | You use test.projects and relied on isolation from root config |
Every row is confirmed against Vitest’s own migration guide, not summarized from memory. Full mechanism, exact error text where one exists, and the fix live in each linked post below.
The 10 changes, in detail
- Fix Vitest 5 vi.mock Top-Level Scope Error:
vi.mock,vi.unmock, andvi.hoistednow throw if called outside module top level, instead of just warning. - Fix Vitest 5 clearMocks Breaking Mock State:
clearMocksflips totrueby default, wiping mock call history before every test. - Fix Vitest 5 test.sequential Removed Error:
test.sequential/describe.sequentialare gone; use{ concurrent: false }instead. - Fix Vitest 5 Config Not Found in Parent Directory: Vitest stops searching parent directories for a config file.
- Fix Vitest 5 bench No Longer Top-Level Export: benchmarks move inside
test()as a context fixture; severalbenchmark.*config options are removed. - Fix Vitest 5 Unawaited Async Assertion Error: a forgotten
awaiton an async assertion now fails the test instead of just warning. - Fix Vitest 5 expect.poll Timeout Error:
expect.poll()actively rejects on timeout instead of letting a late result still pass. - Fix Vitest 5 Cannot Find Module vitest/reporters: eight subpath entry points (
vitest/reporters,vitest/coverage, and more) are removed outright. - Fix Vitest 5 toThrow(”) Silently Passing Tests: an empty string is no longer special-cased, so it now matches any thrown error.
- Fix Vitest 5 Projects Not Inheriting Root Config: inline
test.projectsentries now inherit root Vite plugins andsetupFilesby default.
Why cover a beta at all
Most pillars on this site cover a stable release most readers are already running. This one doesn’t, and that’s worth being upfront about rather than glossing over: Vitest 5.0 was still in beta (v5.0.0-beta.7, 2026-07-24) at the time this was researched, and this repo’s own test suite hasn’t upgraded past vitest@^3.0.0. The case for covering it anyway: the migration guide already documents 33 distinct breaking changes against a real, shipping beta, not a speculative RFC, and several of them (the mocking defaults especially) are exactly the kind of silent behavior change that’s worth knowing about before it surfaces as a confusing failure the week Vitest 5 goes stable and a dependency update pulls it in without anyone reading a changelog first.
If you’re evaluating whether to adopt the beta now versus wait for stable, that’s a real decision this guide doesn’t make for you - it only tries to make sure you’re not surprised by what’s actually in it either way.
Browse the rest of the Guides & Fixes archive for more framework and tooling breaking-change coverage.







