{"record":{"id":"f0646e63f2dc0880","repo":"angular/angular.js","slug":"no-raf-callbacks-present","errorCode":null,"errorMessage":"No rAF callbacks present","messagePattern":"No rAF callbacks present","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/ngMock/angular-mocks.js","lineNumber":2405,"sourceCode":"\n  return $delegate;\n}];\n\nangular.mock.$RAFDecorator = ['$delegate', function($delegate) {\n  var rafFn = function(fn) {\n    var index = rafFn.queue.length;\n    rafFn.queue.push(fn);\n    return function() {\n      rafFn.queue.splice(index, 1);\n    };\n  };\n\n  rafFn.queue = [];\n  rafFn.supported = $delegate.supported;\n\n  rafFn.flush = function() {\n    if (rafFn.queue.length === 0) {\n      throw new Error('No rAF callbacks present');\n    }\n\n    var length = rafFn.queue.length;\n    for (var i = 0; i < length; i++) {\n      rafFn.queue[i]();\n    }\n\n    rafFn.queue = rafFn.queue.slice(i);\n  };\n\n  return rafFn;\n}];\n\n/**\n *\n */\nvar originalRootElement;\nangular.mock.$RootElementProvider = function() {","sourceCodeStart":2387,"sourceCodeEnd":2423,"githubUrl":"https://github.com/angular/angular.js/blob/d8f77817eb5c98dec5317bc3756d1ea1812bcfbe/src/ngMock/angular-mocks.js#L2387-L2423","documentation":"ngMock decorates $$rAF with a queue and a flush() that runs all queued requestAnimationFrame callbacks (then re-slices the queue in case callbacks cancelled or queued more). Flushing an empty queue means nothing scheduled a frame, so it throws 'No rAF callbacks present' — same 'nothing to flush' contract as the other mock flushes.","triggerScenarios":"Calling $$rAF.flush() with no rAF callbacks registered: the code path that calls $$rAF(fn) (often via $animate or a rAF-based directive) never ran; a previous $animate.flush() already drained the $$rAF queue and then the test flushes it again.","commonSituations":"Manually flushing $$rAF in animation tests while $animate.flush() also drains it internally, so the second flush finds an empty queue; rAF scheduling hidden behind a condition (element attached, class change) that the test did not satisfy.","solutions":["Guard the flush: only call $$rAF.flush() when $$rAF.queue.length > 0.","Trigger the code that schedules the rAF callback before flushing.","Drop the manual $$rAF.flush() if $animate.flush() already ran — it flushes the rAF queue as part of its loop."],"exampleFix":"// before\n$animate.flush();\n$$rAF.flush(); // throws: queue already drained above\n\n// after\n$animate.flush();\nif ($$rAF.queue.length) {\n  $$rAF.flush();\n}","handlingStrategy":"validation","validationCode":"// Guard the rAF flush by queue length\ninject(function($$rAF) {\n  if ($$rAF.queue.length > 0) {\n    $$rAF.flush();\n  }\n});","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not manually flush $$rAF after $animate.flush() — it already drains the rAF queue.","Trigger the code that schedules the frame callback before flushing."],"tags":["angular-mocks","requestanimationframe","animation","flush","testing"],"backgroundTag":"empty-flush-queue","analyzedSha":"d8f77817eb5c98dec5317bc3756d1ea1812bcfbe","analyzedAt":"2026-08-21T20:36:31.651Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}