angular/angular.js · error · Error

Injector already created, can not register a module!

Error message

Injector already created, can not register a module!

What it means

angular.mock.module(...) (window.module) only QUEUES module registrations; the queue is consumed when the injector is first created for the current spec. Its workFn runs at injector-creation time, and if currentSpec.$injector is already set — inject() has already run for this spec — no further modules can be registered, so it throws 'Injector already created, can not register a module!'.

Source

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

   * This function registers a module configuration code. It collects the configuration information
   * which will be used when the injector is created by {@link angular.mock.inject inject}.
   *
   * See {@link angular.mock.inject inject} for usage example
   *
   * @param {...(string|Function|Object)} fns any number of modules which are represented as string
   *        aliases or as anonymous module initialization functions. The modules are used to
   *        configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an
   *        object literal is passed each key-value pair will be registered on the module via
   *        {@link auto.$provide $provide}.value, the key being the string name (or token) to associate
   *        with the value on the injector.
   */
  var module = window.module = angular.mock.module = function() {
    var moduleFns = Array.prototype.slice.call(arguments, 0);
    return wasInjectorCreated() ? workFn() : workFn;
    /////////////////////
    function workFn() {
      if (currentSpec.$injector) {
        throw new Error('Injector already created, can not register a module!');
      } else {
        var fn, modules = currentSpec.$modules || (currentSpec.$modules = []);
        angular.forEach(moduleFns, function(module) {
          if (angular.isObject(module) && !angular.isArray(module)) {
            fn = ['$provide', function($provide) {
              angular.forEach(module, function(value, key) {
                $provide.value(key, value);
              });
            }];
          } else {
            fn = module;
          }
          if (currentSpec.$providerInjector) {
            currentSpec.$providerInjector.invoke(fn);
          } else {
            modules.push(fn);
          }
        });

View on GitHub (pinned to d8f77817eb)

Solutions

  1. Declare ALL modules before anything injects: put beforeEach(module('a', 'b')) physically before any beforeEach that uses inject().
  2. Inside a single it(), order it module(...) first, then inject(...) — never inject then module.
  3. For per-test variation, register one parameterized module in the outer setup whose config reads a mutable flag/variable the test sets before inject() creates the injector.

Example fix

// before
var $httpBackend;
beforeEach(inject(function(_$httpBackend_) {
  $httpBackend = _$httpBackend_; // injector created here
}));
beforeEach(module('mock.responses')); // throws: injector already created

// after
beforeEach(module('mock.responses')); // register modules FIRST
beforeEach(inject(function(_$httpBackend_) {
  $httpBackend = _$httpBackend_;
}));
Defensive patterns

Strategy: validation

Validate before calling

// Enforce ordering in shared setup: all module() calls before any inject()
beforeEach(module('app', 'app.templates', 'test.stubs'));
// only AFTER the module hooks:
beforeEach(inject(function(_$httpBackend_) { /* ... */ }));

Try / catch

// Fail with actionable guidance when module() is called too late
try {
  module('late.module');
} catch (e) {
  if (/Injector already created/.test(e.message)) {
    throw new Error('Move this module() into a beforeEach that runs before any inject()');
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling module(...) inside an it() after an inject() has run; calling module(...) inside a function passed to inject(); a beforeEach(module(...)) declared after another beforeEach whose function already called inject(); a lazy helper that registers modules on first use, triggered mid-test.

Common situations: Mixing module() and inject() in the same spec in the wrong order; trying to register a per-test override module after the injectable fixtures were created; Jasmine beforeAll-style shared setup that injects, followed by per-test module() calls; the module() call is deferred (returned function) and invoked too late.

Related errors


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