angular/angular.js · error · Error

Expected $log to be empty! Either a message was logged unexp

Error message

Expected $log to be empty! Either a message was logged unexpectedly, or an expected log message was not checked and removed:

What it means

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.

Source

Thrown at src/ngMock/angular-mocks.js:556

     * @description
     * Assert that all of the logging methods have no logged messages. If any messages are present,
     * an exception is thrown.
     */
    $log.assertEmpty = function() {
      var errors = [];
      angular.forEach(['error', 'warn', 'info', 'log', 'debug'], function(logLevel) {
        angular.forEach($log[logLevel].logs, function(log) {
          angular.forEach(log, function(logItem) {
            errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' +
                        (logItem.stack || ''));
          });
        });
      });
      if (errors.length) {
        errors.unshift('Expected $log to be empty! Either a message was logged unexpectedly, or ' +
          'an expected log message was not checked and removed:');
        errors.push('');
        throw new Error(errors.join('\n---------\n'));
      }
    };

    $log.reset();
    return $log;
  };
};


/**
 * @ngdoc service
 * @name $interval
 *
 * @description
 * Mock implementation of the $interval service.
 *
 * Use {@link ngMock.$interval#flush `$interval.flush(millis)`} to
 * move forward by `millis` milliseconds and trigger any functions scheduled to run in that

View on GitHub (pinned to d8f77817eb)

Solutions

  1. Fix the root cause: make the code (or the mocked responses) not produce the logged message.
  2. If the message is expected, assert it explicitly ($log.error.logs[0][0]) and then call $log.reset() before assertEmpty runs.
  3. Call $log.reset() in tests that intentionally exercise error paths so recorded entries do not leak into a later assertEmpty.

Example fix

// before
it('handles 500', inject(function($httpBackend, $http, $log) {
  $httpBackend.expectGET('/api').respond(500, 'boom');
  $http.get('/api');
  $httpBackend.flush();
  $log.assertEmpty(); // throws: $http logged the 500
}));

// after
it('handles 500', inject(function($httpBackend, $http, $log) {
  $httpBackend.expectGET('/api').respond(500, 'boom');
  $http.get('/api');
  $httpBackend.flush();
  expect($log.error.logs.length).toBe(1); // assert it, then clear
  $log.reset();
}));
Defensive patterns

Strategy: validation

Validate before calling

// Check recorded logs yourself before asserting emptiness
function logLevelsEmpty($log) {
  return ['error', 'warn', 'info', 'log', 'debug'].every(function(level) {
    return $log[level].logs.length === 0;
  });
}
if (!logLevelsEmpty($log)) {
  // assert/clear specific entries first, then $log.reset()
}

Try / catch

// Let assertEmpty run, but surface the entries it collected on failure
try {
  $log.assertEmpty();
} catch (e) {
  // e.message already contains each MOCK $log line + stack; rethrow with spec name
  throw new Error(specName + ' failed assertEmpty:\n' + e.message);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of angular/angular.js@d8f77817eb (2026-08-21). Data as JSON: /api/errors/25643e1ea8749d20. Report an issue: GitHub.