Skip to content

[Bug]: @storybook/react + @storybook/addon-vitest emits act(async) without await warnings in multi-file Vitest browser-mode runs #34708

@IRusio

Description

@IRusio

Describe the bug

When running multiple story files through @storybook/addon-vitest in Vitest browser mode, React emits the following warning for every ~0.66 stories in a large suite:

Warning: You called act(async () => ...) without await. This could lead to unexpected testing behaviour, interleaving multiple act calls and mixing their scopes. You should - await act(async () => ...);

The warning is deterministic. The count is identical across independent runs and scales with the number of story files in the invocation, but it does not appear in any single-file run.

Refreshed duplicate search on 2026-05-04 found no matching storybookjs/storybook issue for the exact warning text or for the broader addon-vitest act / react act vitest browser wording.

To Reproduce

Any Storybook 10.x project running stories via @storybook/addon-vitest with Vitest browser mode using the Playwright provider and at least ~20 story files. Minimal repro repo available on request.

Scope act(async) warnings
1 file, any single story 0
2 files together 0
26 files, e.g. one UI-primitives directory 8
196 files, full suite, 722 tests 130

Configurations attempted

Each of the following produced exactly 130 warnings, with no change:

  1. test.fileParallelism: false, fully serial execution and about 2x slower.
  2. test.isolate: true plus browser.isolate: true.
  3. Local patch to @storybook/[email protected] renderToCanvas.tsx adding await before the tail recursion of processActQueue() at line 115 of the bundled chunk-L3JF7GGZ.js.

Every single-file run remained clean regardless of configuration.

Root cause suspected

@storybook/react/src/act-compat.ts wraps React's act with withGlobalActEnvironment, which sets globalThis.IS_REACT_ACT_ENVIRONMENT = true synchronously and restores it only when the returned pseudo-thenable's .then is invoked. If any caller in the story-render pipeline creates this thenable but fails to await it, the flag stays true across story boundaries and React's internal act-scope tracking reports "interleaving multiple act calls" on the next independent act call.

The actQueue-based serialization in renderToCanvas was verified as not the source because the await patch did not change the warning count. The leaking caller appears to be elsewhere in the pipeline, possibly the decorators chain, play() lifecycle, or an async teardown path fired after resolve().

Expected behavior

Multi-file Vitest browser-mode suites should emit zero framework-generated act(async) warnings when no per-story user code calls act directly.

System

  • @storybook/react: 10.3.5
  • @storybook/addon-vitest: 10.3.5
  • @storybook/react-vite: 10.3.5
  • @storybook/react-dom-shim: 10.3.5
  • vitest: 4.1.4
  • @vitest/browser-playwright: 4.1.4
  • react: 18.3.1
  • playwright: Chromium provider
  • OS: macOS / Darwin

The Storybook next branch was also checked as of 2026-04-18 and appeared affected by the same actQueue / act-compat behavior.

Additional context

Sister-library issues documenting the same warning family, but in different libraries:

We silenced this with a narrow console.error filter in a Vitest setup file as an interim workaround:

const originalConsoleError = globalThis.console.error

globalThis.console.error = (...args: unknown[]) => {
  const formatted = args.map((arg) => String(arg)).join(' ')
  if (
    formatted.includes('You called act(async () => ...) without await') &&
    formatted.includes('interleaving multiple act calls')
  ) {
    return
  }
  originalConsoleError(...args)
}

That workaround is paired with a local guard that fails on any new distinct Storybook act(...) warning signature, so this exact known framework-level warning is the only one suppressed.

Happy to provide a minimal reproduction repo if that is required for triage.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions