{"record":{"id":"25643e1ea8749d20","repo":"angular/angular.js","slug":"expected-log-to-be-empty-either-a-message-was-lo","errorCode":null,"errorMessage":"Expected $log to be empty! Either a message was logged unexpectedly, or an expected log message was not checked and removed:","messagePattern":"Expected \\$log to be empty! Either a message was logged unexpectedly, or an expected log message was not checked and removed:","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/ngMock/angular-mocks.js","lineNumber":556,"sourceCode":"     * @description\n     * Assert that all of the logging methods have no logged messages. If any messages are present,\n     * an exception is thrown.\n     */\n    $log.assertEmpty = function() {\n      var errors = [];\n      angular.forEach(['error', 'warn', 'info', 'log', 'debug'], function(logLevel) {\n        angular.forEach($log[logLevel].logs, function(log) {\n          angular.forEach(log, function(logItem) {\n            errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\\n' +\n                        (logItem.stack || ''));\n          });\n        });\n      });\n      if (errors.length) {\n        errors.unshift('Expected $log to be empty! Either a message was logged unexpectedly, or ' +\n          'an expected log message was not checked and removed:');\n        errors.push('');\n        throw new Error(errors.join('\\n---------\\n'));\n      }\n    };\n\n    $log.reset();\n    return $log;\n  };\n};\n\n\n/**\n * @ngdoc service\n * @name $interval\n *\n * @description\n * Mock implementation of the $interval service.\n *\n * Use {@link ngMock.$interval#flush `$interval.flush(millis)`} to\n * move forward by `millis` milliseconds and trigger any functions scheduled to run in that","sourceCodeStart":538,"sourceCodeEnd":574,"githubUrl":"https://github.com/angular/angular.js/blob/d8f77817eb5c98dec5317bc3756d1ea1812bcfbe/src/ngMock/angular-mocks.js#L538-L574","documentation":"The $log mock records every call to error/warn/info/log/debug in per-level arrays. $log.assertEmpty() throws if any level collected messages, joining each entry (with its stack) under the header 'Expected $log to be empty!'. It is a test assertion that no component — yours or Angular's — logged unexpectedly during the spec.","triggerScenarios":"Any $log.error/warn/info/log/debug call during the test followed by $log.assertEmpty(): a $http request answered with a 4xx/5xx status by the mock backend; a rejected $q promise logged by code under test; ngRoute/ngMessages/UI-Router deprecation or interpolation warnings; stack traces are included because logItem.stack is appended.","commonSituations":"afterEach($log.assertEmpty) added to keep tests clean, then failing because a mocked endpoint returns an error status and $http logs it; a third-party module logs a one-time warning on first digest; an expected error is logged (the test wanted it) but assertEmpty still treats it as a failure because reading logs does not clear them.","solutions":["Fix the root cause: make the code (or the mocked responses) not produce the logged message.","If the message is expected, assert it explicitly ($log.error.logs[0][0]) and then call $log.reset() before assertEmpty runs.","Call $log.reset() in tests that intentionally exercise error paths so recorded entries do not leak into a later assertEmpty."],"exampleFix":"// before\nit('handles 500', inject(function($httpBackend, $http, $log) {\n  $httpBackend.expectGET('/api').respond(500, 'boom');\n  $http.get('/api');\n  $httpBackend.flush();\n  $log.assertEmpty(); // throws: $http logged the 500\n}));\n\n// after\nit('handles 500', inject(function($httpBackend, $http, $log) {\n  $httpBackend.expectGET('/api').respond(500, 'boom');\n  $http.get('/api');\n  $httpBackend.flush();\n  expect($log.error.logs.length).toBe(1); // assert it, then clear\n  $log.reset();\n}));","handlingStrategy":"validation","validationCode":"// Check recorded logs yourself before asserting emptiness\nfunction logLevelsEmpty($log) {\n  return ['error', 'warn', 'info', 'log', 'debug'].every(function(level) {\n    return $log[level].logs.length === 0;\n  });\n}\nif (!logLevelsEmpty($log)) {\n  // assert/clear specific entries first, then $log.reset()\n}","typeGuard":null,"tryCatchPattern":"// Let assertEmpty run, but surface the entries it collected on failure\ntry {\n  $log.assertEmpty();\n} catch (e) {\n  // e.message already contains each MOCK $log line + stack; rethrow with spec name\n  throw new Error(specName + ' failed assertEmpty:\\n' + e.message);\n}","preventionTips":["Call $log.reset() after asserting expected messages, and in tests that intentionally log.","Make mocked error responses (4xx/5xx) deliberate: either assert the $log entry or avoid the error path."],"tags":["angular-mocks","logging","assertion","testing"],"backgroundTag":"unexpected-log-output","analyzedSha":"d8f77817eb5c98dec5317bc3756d1ea1812bcfbe","analyzedAt":"2026-08-21T20:36:31.651Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}