facebook/react · error · Error
Already flushing work.
Error message
Already flushing work.
What it means
SchedulerMock's unstable_flushNumberOfYields(count) drives the queued scheduler callback in a loop until it has produced `count` yielded values (it powers assertion helpers like toFlushAndYieldThrough). Like every flush helper it sets the module-level isFlushing flag for the duration, and it throws 'Already flushing work.' on entry if another flush helper is still running, because the mock's single shared state (expectedNumberOfYields, didStop, yieldedValues) cannot back two interleaved flushes.
Source
Thrown at packages/scheduler/src/forks/SchedulerMock.js:506
function reset() {
if (isFlushing) {
throw new Error('Cannot reset while already flushing work.');
}
currentMockTime = 0;
scheduledCallback = null;
scheduledTimeout = null;
timeoutTime = -1;
yieldedValues = null;
expectedNumberOfYields = -1;
didStop = false;
isFlushing = false;
needsPaint = false;
}
// Should only be used via an assertion helper that inspects the yielded values.
function unstable_flushNumberOfYields(count: number): void {
if (isFlushing) {
throw new Error('Already flushing work.');
}
if (scheduledCallback !== null) {
const cb = scheduledCallback;
expectedNumberOfYields = count;
isFlushing = true;
try {
let hasMoreWork = true;
do {
hasMoreWork = cb(true, currentMockTime);
} while (hasMoreWork && !didStop);
if (!hasMoreWork) {
scheduledCallback = null;
}
} finally {
expectedNumberOfYields = -1;
didStop = false;
isFlushing = false;
}View on GitHub (pinned to eafeac097b)
Solutions
- Make flush helper calls strictly sequential — each toFlush*/unstable_flush* call must fully return before the next one starts.
- Move the nested flush out of the scheduled callback or effect: run the outer flush to completion, then assert on remaining work.
- Remove defensive 'flush just in case' calls from shared test-utils that may execute inside an active flush.
- If React work itself triggers the nested flush, split the test into two top-level flushes instead of nesting.
Example fix
// before
Scheduler.scheduleCallback(NormalPriority, () => {
Scheduler.log('a');
Scheduler.unstable_flushNumberOfYields(1); // throws: already flushing
});
Scheduler.unstable_flushAll();
// after
Scheduler.scheduleCallback(NormalPriority, () => {
Scheduler.log('a');
});
expect(Scheduler).toFlushAndYieldThrough(['a']); // one flush helper at a time Defensive patterns
Strategy: validation
Validate before calling
// Guard every flush entry point with your own flag.
let flushing = false;
function safeFlushNumberOfYields(Scheduler: any, count: number) {
if (flushing) return; // skip instead of throwing
flushing = true;
try {
Scheduler.unstable_flushNumberOfYields(count);
} finally {
flushing = false;
}
} Try / catch
try {
Scheduler.unstable_flushNumberOfYields(2);
} catch (e) {
if (e instanceof Error && e.message.includes('Already flushing work')) {
// a flush is already on the stack; move this call after it returns
} else {
throw e;
}
} Prevention
- Call flush helpers only from the top level of a test, never from task callbacks or effects.
- One assertion helper (toFlush*) per flush; do not chain them re-entrantly.
- Keep shared test-utils free of defensive 'flush just in case' calls.
When it happens
Trigger: Invoking Scheduler.unstable_flushNumberOfYields(n) — directly or via expect(Scheduler).toFlushAndYieldThrough([...]) — from inside a callback, effect, or assertion helper that is itself being flushed by unstable_flushAll(), unstable_flushAllWithoutAsserting(), or another flush helper.
Common situations: Custom test helpers that 'ensure flushed' state by flushing at the start; component effects that flush scheduler work during act(); copy-pasted test-utils calling toFlush* helpers defensively inside teardown; nested test-runner hooks.
Related errors
- Cannot reset while already flushing work.
- Log is not empty. Assert on the log of yielded values before
- While flushing work, something yielded a value. Use an asser
- react-dom/unstable_testing is not supported in React Server
- 95
AI-assisted analysis of facebook/react@eafeac097b (2026-08-21).
Data as JSON: /api/errors/fc6bd707cebb081e.
Report an issue: GitHub.