1

Getting the error Error: [$injector:unpr] Unknown provider: IdleProvider in my application when it is deployed to our staging server using dokku but I am not getting it when running it on my local machine. I'm using ng-idle 1.2.1

I've found this question asked a number of times but the cause was always related to the changes made in version 1.0.0 where the service names were changed. The only thing I can think of is that the minification of the code is the problem but as far as I can see the code should be ok but I am not an expert. Any help would be greatly appreciated.

It's written in Coffeescript

configuration = (RestangularProvider, $logProvider, growlProvider, IdleProvider, KeepaliveProvider) ->
  .
  .
  .
  return

configuration.$inject = [
  'RestangularProvider'
  '$logProvider'
  'growlProvider'
  'IdleProvider'
  'KeepaliveProvider'
]

angular
  .module 'vssApp.config', [
    'restangular'
  ]
  .config configuration

EDIT

While trying to replicate the problem on my local machine I removed the 'ngIdle' module in the modules array below. This resulted in the same behavior so I am assuming that the problem stems from the ngIdle module not being loaded correctly here. I still feel that minification could be causing the problem but, again, I'm not sure why or how to fix it.

modules = [
  'ui.router'
  'ui.bootstrap'
  'ui.select'
  'ngAnimate'
  'ngMessages'
  'ngSanitize'
  'ngCookies'
  'smart-table'
  'angularMoment'
  'templates'
  'angular-storage'
  'angular-growl'
  'vssApp.core.auth'
  'vssApp.core.loading'
  'ngIdle'
  'cgPrompt'
  'vssApp.filters'
]

runBlock.$inject = [
  '$templateCache'
]

angular
  .module 'vssApp.core', modules
  .run runBlock

EDIT 2

Here's the full output from the error message I'm getting

Error: [$injector:modulerr] Failed to instantiate module vssApp due to:
Error: [$injector:modulerr] Failed to instantiate module vssApp.config due to:
Error: [$injector:unpr] Unknown provider: IdleProvider
http://errors.angularjs.org/1.3.16/$injector/unpr?p0=IdleProvider
    at https://SERVER/assets/application-85a5fd382c73380bf2a71b66e581c941.js:3:18814
    at https://SERVER/assets/application-85a5fd382c73380bf2a71b66e581c941.js:4:16489
    at getService (https://SERVER/assets/application-85a5fd382c73380bf2a71b66e581c941.js:4:14903)
    at Object.invoke (https://SERVER/assets/application-85a5fd382c73380bf2a71b66e581c941.js:4:15466)
    at runInvokeQueue (https://SERVER/assets/application-85a5fd382c73380bf2a71b66e581c941.js:4:13793)
    at https://SERVER/assets/application-85a5fd382c73380bf2a71b66e581c941.js:4:14062
    at forEach (https://SERVER/assets/application-85a5fd382c73380bf2a71b66e581c941.js:3:19482)
    at loadModules (https://SERVER/assets/application-85a5fd382c73380bf2a71b66e581c941.js:4:13587)
    at https://SERVER/assets/application-85a5fd382c73380bf2a71b66e581c941.js:4:13964
    at forEach (https://SERVER/assets/application-85a5fd382c73380bf2a71b66e581c941.js:3:19482)
http://errors.angularjs.org/1.3.16/$injector/modulerr?p0=vssApp.config&p1=E…net%2Fassets%2Fapplication-85a5fd382c73380bf2a71b66e581c941.js%3A3%3A19482)
    at https://SERVER/assets/application-85a5fd382c73380bf2a71b66e581c941.js:3:18814
    at https://SERVER/assets/application-85a5fd382c73380bf2a71b66e581c941.js:4:14406
    at forEach (https://SERVER/assets/application-85a5fd382c73380bf2a71b66e581c941.js:3:19482)
    at loadModules (https://SERVER/assets/application-85a5fd382c73380bf2a71b66e581c941.js:4:13587)
    at https://SERVER/assets/application-85a5fd382c73380bf2a71b66e581c941.js:4:13964
    at forEach (https://SERVER/assets/application-85a5fd382c73380bf2a71b66e581c941.js:3:19482)
    at loadModules (https://SERVER/assets/application-85a5fd382c73380bf2a71b66e581c941.js:4:13587)
    at createInjector (https://SERVER/assets/application-85a5fd382c73380bf2a71b66e581c941.js:4:16844)
    at doBootstrap (https://SERVER/assets/application-85a5fd382c73380bf2a71b66e581c941.js:3:28466)
    at bootstrap (https://SERVER/assets/application-85a5fd382c73380bf2a71b66e581c941.js:3:28995)
http://errors.angularjs.org/1.3.16/$injector/modulerr?p0=vssApp&p1=Error%3A…net%2Fassets%2Fapplication-85a5fd382c73380bf2a71b66e581c941.js%3A3%3A28995)
cyclic
  • 402
  • 1
  • 6
  • 17

2 Answers2

0

A rule of thumb is to load modules dependencies in each place where they are used. This allows to decouple them. And this eliminates race condition with service provider injection.

If the app looks like this

angular.module('vssApp', ['vssApp.config', 'ngIdle', ...])..
angular.module('vssApp.config', ['restangular'])...

service provider for Idle service is not defined at the time when vssApp.config module is loaded.

While this

angular.module('vssApp', ['ngIdle', 'vssApp.config', ...])
angular.module('vssApp.config', ['restangular'])...

avoids race condition but still indicates code smell.

It should be

angular.module('vssApp.config', ['restangular', 'ngIdle'])...

This issue applies to service providers only and config phase. Service instances can be injected for any module order.

Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • I absolutely see the merits of loading dependencies individually as you've outlined above and I will change this in the future but it still doesn't explain the problem I'm having. If it did then the problem should exist when I run the code locally but I am only seeing it on our staging server after it's been deployed. – cyclic Jun 22 '16 at 15:17
  • @RobbieNolan It may depend on some circumstances that stay behind the scene, like how the app is built. It is still not clear how `vssApp.config` fits in with the code above. You haven't cited full error message, and it is not evident that the error appears in `vssApp.config`. Any way, if `ngIdle` is loaded in each and every module that makes use of its services, this should solve the problem. – Estus Flask Jun 22 '16 at 15:33
  • I followed your advice and I am now loading `ngIdle` in every module that uses it but still the same error remains. I am at a loss as to what is causing this problem. – cyclic Jun 23 '16 at 08:32
  • @RobbieNolan Please, provide full error message with call stack, so the problem could be narrowed down to particular block. Is it still `vssApp.config`? – Estus Flask Jun 23 '16 at 12:37
  • I've added the error output to my original question. Yes, it is still coming from vssApp.config – cyclic Jun 23 '16 at 14:06
  • If you've done the thing that was described in the answer, and `ngIdle` is loaded in `vssApp.config`, the only possibility why `IdleProvider` isn't there is that `ng-idle` wasn't bundled correctly or wasn't required correctly - if CJS modules are used. Make sure that `.provider("Idle"` or `.provider('Idle'` string presents in `application-85a5fd382c73380bf2a71b66e581c941.js` and `ng-idle` module was defined/required *before app bootstrapping*. This isn't related to minification, hope this narrows down the issue for you. – Estus Flask Jun 23 '16 at 14:44
0

Finally found the cause and solution to this, it seems to have been a bower issue.

It's a Rails app, so I specified ng-idle 1.2.1 in the bower.json file but for some reason the bower file was ignored when the app was being deployed using Dokku and the last installed version 0.3.5 remained, which meant that the pre-1.0.0 ng-idle services naming convention was still being used where all service names were preceded with a $. This resulted in the Unknown provider: IdleProvider error because $IdleProvider was the actual service name.

In the end I had to connect to the docker container and remove and reinstall all bower components. Running bower update as part of the deployment was not enough for some reason. When I have more time I will investigate what caused this behavior and I will report here.

cyclic
  • 402
  • 1
  • 6
  • 17
  • The proper course of action would probably be to unignore your `bower.json`, which should then hopefully cause `bower update` to pick up the proper version of that dependency. – Jose Diaz-Gonzalez Jun 29 '16 at 17:08