{"record":{"id":"f5efafd5e3a0de62","repo":"angular/angular.js","slug":"no-deferred-tasks-to-be-flushed","errorCode":null,"errorMessage":"No deferred tasks to be flushed","messagePattern":"No deferred tasks to be flushed","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/ngMock/angular-mocks.js","lineNumber":139,"sourceCode":"   * @description\n   * Flushes all pending requests and executes the defer callbacks.\n   *\n   * See {@link ngMock.$flushPendingsTasks} for more info.\n   *\n   * @param {number=} number of milliseconds to flush. See {@link #defer.now}\n   */\n  self.defer.flush = function(delay) {\n    var nextTime;\n\n    if (angular.isDefined(delay)) {\n      // A delay was passed so compute the next time\n      nextTime = self.defer.now + delay;\n    } else if (self.deferredFns.length) {\n      // No delay was passed so set the next time so that it clears the deferred queue\n      nextTime = self.deferredFns[self.deferredFns.length - 1].time;\n    } else {\n      // No delay passed, but there are no deferred tasks so flush - indicates an error!\n      throw new Error('No deferred tasks to be flushed');\n    }\n\n    while (self.deferredFns.length && self.deferredFns[0].time <= nextTime) {\n      // Increment the time and call the next deferred function\n      self.defer.now = self.deferredFns[0].time;\n      var task = self.deferredFns.shift();\n      taskTracker.completeTask(task.fn, task.type);\n    }\n\n    // Ensure that the current time is correct\n    self.defer.now = nextTime;\n  };\n\n  /**\n   * @name $browser#defer.getPendingTasks\n   *\n   * @description\n   * Returns the currently pending tasks that need to be flushed.","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/angular/angular.js/blob/d8f77817eb5c98dec5317bc3756d1ea1812bcfbe/src/ngMock/angular-mocks.js#L121-L157","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nit('polls after delay', inject(function($timeout, poller) {\n  $timeout.flush(); // throws: nothing scheduled yet\n  poller.start();\n}));\n\n// after\nit('polls after delay', inject(function($timeout, poller) {\n  poller.start();            // schedules the $timeout\n  $timeout.flush();          // now has something to flush\n}));","handlingStrategy":"validation","validationCode":"// Inject the mock browser and flush only when work is pending\nfunction flushTimeouts($browser) {\n  if ($browser.defer.getPendingTasks().length > 0) {\n    $browser.defer.flush();\n  }\n}\n// usage: inject(function($browser){ flushTimeouts($browser); })","typeGuard":null,"tryCatchPattern":"// Wrap flush in a helper that adds context on the 'nothing to flush' case\ntry {\n  $timeout.flush();\n} catch (e) {\n  if (/No deferred tasks to be flushed/.test(e.message)) {\n    throw new Error('Test bug: no $timeout pending when flush() was called');\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["angular-mocks","timeout","flush","testing","async"],"backgroundTag":"empty-flush-queue","analyzedSha":"d8f77817eb5c98dec5317bc3756d1ea1812bcfbe","analyzedAt":"2026-08-21T20:36:31.651Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}