facebook/react · error · Error
Cannot reset while already flushing work.
Error message
Cannot reset while already flushing work.
What it means
The Scheduler package ships a test-only mock (imported in Jest via jest.mock('scheduler', () => jest.requireActual('scheduler/unstable_mock'))) whose flush helpers run queued callbacks in a synchronous do-while loop while a module-level isFlushing flag is set. unstable_reset() wipes every piece of mock state (currentMockTime, scheduledCallback, yieldedValues, expectedNumberOfYields), and it throws 'Cannot reset while already flushing work.' when called mid-flush, because nulling that state underneath the running loop would corrupt the flush invariants. It is a test-harness invariant error, never a production scheduler error.
Source
Thrown at packages/scheduler/src/forks/SchedulerMock.js:490
) {
// We yielded at least as many values as expected. Stop flushing.
didStop = true;
return true;
}
return false;
}
function getCurrentTime(): number {
return currentMockTime;
}
function forceFrameRate() {
// No-op
}
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) {View on GitHub (pinned to eafeac097b)
Solutions
- Call Scheduler.unstable_reset() only between flushes — e.g. at the top of beforeEach/afterEach after the previous flush helper has fully returned — never from inside a scheduled callback.
- To stop work from inside a task, return false (signal no more work) instead of resetting the mock.
- Wrap custom flush wrappers in try/finally so the flush always fully unwinds before any reset runs.
- If you share harness code, track your own flushing flag around every flush call and make reset a no-op while it is set.
Example fix
// before
Scheduler.scheduleCallback(NormalPriority, () => {
Scheduler.unstable_reset(); // throws: a flush is running this callback
});
Scheduler.unstable_flushAll();
// after
Scheduler.scheduleCallback(NormalPriority, () => {
Scheduler.log('work');
});
Scheduler.unstable_flushAll();
Scheduler.unstable_reset(); // safe: no flush on the stack Defensive patterns
Strategy: validation
Validate before calling
// The mock exposes no isFlushing getter — track flush nesting yourself.
let flushing = false;
function flush<T>(run: () => T): T {
if (flushing) throw new Error('nested flush');
flushing = true;
try {
return run();
} finally {
flushing = false;
}
}
function safeReset(Scheduler: any) {
if (!flushing) Scheduler.unstable_reset(); // skip instead of throwing
} Try / catch
try {
Scheduler.unstable_reset();
} catch (e) {
if (e instanceof Error && e.message.includes('Cannot reset while already flushing')) {
// defer the reset until the active flush helper returns
} else {
throw e;
}
} Prevention
- Never call unstable_reset() from inside a scheduled callback or an assertion helper that runs during a flush.
- Keep reset calls at the top level of tests (beforeEach/afterEach), after flush helpers have returned.
- Treat the scheduler mock as single-entrant: at most one flush helper on the stack at any time.
When it happens
Trigger: Calling Scheduler.unstable_reset() from inside a task callback that unstable_flushAll(), unstable_flushNumberOfYields(), unstable_flushUntilNextPaint(), unstable_flushExpired(), or unstable_flushAllWithoutAsserting() is currently executing; or a nested helper (afterEach, custom act() wrapper) invoking reset() on the same stack as an active flush that has not unwound.
Common situations: Refactoring React component tests that drive the scheduler mock manually; a task callback tries to 'clean up between scenarios' by resetting the mock; shared test-utils that wrap flushes without try/finally; state leaking between tests when a prior test aborted mid-flush.
Related errors
- 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/73c898bea7aaf688.
Report an issue: GitHub.