angular/angular.js · error · Error
No deferred tasks to be flushed
Error message
No deferred tasks to be flushed
What it means
ngMock replaces the browser with a mock that queues every deferred task (mainly $timeout callbacks) on $browser.defer. defer.flush([delay]) advances the mock clock and runs those tasks; $timeout.flush() delegates to it. When you call flush() with no delay argument and the deferred queue is empty, there is nothing to compute a 'next time' from, which almost always means the test's assumptions are wrong, so it throws immediately.
Source
Thrown at src/ngMock/angular-mocks.js:139
* @description
* Flushes all pending requests and executes the defer callbacks.
*
* See {@link ngMock.$flushPendingsTasks} for more info.
*
* @param {number=} number of milliseconds to flush. See {@link #defer.now}
*/
self.defer.flush = function(delay) {
var nextTime;
if (angular.isDefined(delay)) {
// A delay was passed so compute the next time
nextTime = self.defer.now + delay;
} else if (self.deferredFns.length) {
// No delay was passed so set the next time so that it clears the deferred queue
nextTime = self.deferredFns[self.deferredFns.length - 1].time;
} else {
// No delay passed, but there are no deferred tasks so flush - indicates an error!
throw new Error('No deferred tasks to be flushed');
}
while (self.deferredFns.length && self.deferredFns[0].time <= nextTime) {
// Increment the time and call the next deferred function
self.defer.now = self.deferredFns[0].time;
var task = self.deferredFns.shift();
taskTracker.completeTask(task.fn, task.type);
}
// Ensure that the current time is correct
self.defer.now = nextTime;
};
/**
* @name $browser#defer.getPendingTasks
*
* @description
* Returns the currently pending tasks that need to be flushed.View on GitHub (pinned to d8f77817eb)
Solutions
- Make sure the code that schedules the $timeout runs before $timeout.flush() (call the service/controller method first, then flush).
- If the timeout may legitimately have been cancelled or already run, guard the flush: only flush when $browser.defer.getPendingTasks().length > 0.
- If you only want to advance the clock regardless of pending work, pass an explicit delay: $timeout.flush(500) does not throw on an empty queue.
- In afterEach, use $verifyNoPendingTasks('$timeout') to assert state explicitly instead of blindly flushing.
Example fix
// before
it('polls after delay', inject(function($timeout, poller) {
$timeout.flush(); // throws: nothing scheduled yet
poller.start();
}));
// after
it('polls after delay', inject(function($timeout, poller) {
poller.start(); // schedules the $timeout
$timeout.flush(); // now has something to flush
})); Defensive patterns
Strategy: validation
Validate before calling
// Inject the mock browser and flush only when work is pending
function flushTimeouts($browser) {
if ($browser.defer.getPendingTasks().length > 0) {
$browser.defer.flush();
}
}
// usage: inject(function($browser){ flushTimeouts($browser); }) Try / catch
// Wrap flush in a helper that adds context on the 'nothing to flush' case
try {
$timeout.flush();
} catch (e) {
if (/No deferred tasks to be flushed/.test(e.message)) {
throw new Error('Test bug: no $timeout pending when flush() was called');
}
throw e;
} Prevention
- Always run the code that schedules the timeout before calling $timeout.flush().
- Call flush() exactly once per scheduled batch of timeouts you expect.
- Prefer $verifyNoPendingTasks('$timeout') in afterEach over blind flushes.
When it happens
Trigger: Calling $timeout.flush() or $browser.defer.flush() before the code under test has scheduled a $timeout; calling flush a second time after an earlier flush already drained the queue; calling flush after $timeout.cancel() removed the only pending task; calling $timeout.flush() when the async work was actually done with bare $q promises (those are flushed by $digest, not by defer.flush).
Common situations: Test calls $timeout.flush() before invoking the service method that starts the timer; a debounce/poll service cancels its timer on $destroy so nothing is pending; two flush() calls written for one expected timeout; passing flush(delay) is tolerant of an empty queue (nextTime = now + delay, loop no-ops), so intermittent tests that sometimes have zero timers only fail when they call flush() without an argument.
Related errors
- Deferred tasks to flush ({}): {}
- No pending animations ready to be closed or flushed
- No pending request to flush !
- No more pending request to flush !
- Unflushed requests: {} {}
AI-assisted analysis of angular/angular.js@d8f77817eb (2026-08-21).
Data as JSON: /api/errors/f5efafd5e3a0de62.
Report an issue: GitHub.