title: How to debug circular dependency errors in angularjs
body: <p>I am merging a separate angular app ui with my MEAN js application and getting the following error in my browser console</p>
  
  <pre><code>Uncaught Error: [$injector:cdep] Circular dependency found: $http &lt;- $templateRequest &lt;- $$animateQueue &lt;- $animate &lt;- toastr &lt;- mvNotifier &lt;- authInterceptor &lt;- $http &lt;- Auth
  http://errors.angularjs.org/1.4.7/$injector/cdep?p0=%24http%20%3C-%20%24tem…0%3C-%20mvNotifier%20%3C-%20authInterceptor%20%3C-%20%24http%20%3C-%20Auth
  </code></pre>
  
  <p>Now after visiting the error page I understood what it means but I wanted to know how to debug such errors and in which services or controllers to loop for fixing such errors </p>
  
  <p>[UPDATE]</p>
  
  <p>So, my Auth module is like this: </p>
  
  <pre><code>'use strict';
  
  angular.module('aarthikApp')
      .factory('Auth', function Auth($rootScope, $location,  $http, $q , $cookieStore, User) {
          var currentUser = {};
          if ($cookieStore.get('token')) {
              currentUser = User.get();
          }
  
          return {
  
              /**
               * Authenticate user and save token
               *
               * @param  {Object}   user     - login info
               * @param  {Function} callback - optional
               * @return {Promise}
               */
              login: function (user, callback) {
                  var cb = callback || angular.noop;
                  var deferred = $q.defer();
  
                  $http.post('/auth/local', {
                      email: user.email,
                      password: user.password
                  }).
                      success(function (data) {
                          $cookieStore.put('token', data.token);
                          currentUser = User.get();
                          deferred.resolve(data);
                          return cb();
                      }).
                      error(function (err) {
                          this.logout();
                          deferred.reject(err);
                          return cb(err);
                      }.bind(this));
  
                  return deferred.promise;
              },
  
              /**
               * Delete access token and user info
               *
               * @param  {Function}
               */
              logout: function () {
                  $cookieStore.remove('token');
                  currentUser = {};
              },
  
              /**
               * Create a new user
               *
               * @param  {Object}   user     - user info
               * @param  {Function} callback - optional
               * @return {Promise}
               */
              createUser: function (user, callback) {
                  var cb = callback || angular.noop;
  
                  return User.save(user,
                      function (data) {
                          $cookieStore.put('token', data.token);
                          currentUser = User.get();
                          return cb(user);
                      },
                      function (err) {
                          this.logout();
                          return cb(err);
                      }.bind(this)).$promise;
              },
  
              /**
               * Change password
               *
               * @param  {String}   oldPassword
               * @param  {String}   newPassword
               * @param  {Function} callback    - optional
               * @return {Promise}
               */
              changePassword: function (oldPassword, newPassword, callback) {
                  var cb = callback || angular.noop;
  
                  return User.changePassword({ id: currentUser._id }, {
                      oldPassword: oldPassword,
                      newPassword: newPassword
                  }, function (user) {
                      return cb(user);
                  }, function (err) {
                      return cb(err);
                  }).$promise;
              },
  
              /**
               * Gets all available info on authenticated user
               *
               * @return {Object} user
               */
              getCurrentUser: function () {
                  return currentUser;
              },
  
              /**
               * Check if a user is logged in
               *
               * @return {Boolean}
               */
              isLoggedIn: function () {
                  return currentUser.hasOwnProperty('role');
              },
  
              /**
               * Waits for currentUser to resolve before checking if user is logged in
               */
              isLoggedInAsync: function (cb) {
                  if (currentUser.hasOwnProperty('$promise')) {
                      currentUser.$promise.then(function () {
                          cb(true);
                      }).catch(function () {
                          cb(false);
                      });
                  } else if (currentUser.hasOwnProperty('role')) {
                      cb(true);
                  } else {
                      cb(false);
                  }
              },
  
              /**
               * Check if a user is an admin
               *
               * @return {Boolean}
               */
              isAdmin: function () {
                  return currentUser.role === 'admin';
              },
              isBroker: function () {
                  return currentUser.role === 'broker';
              },
  
              /**
               * Get auth token
               */
              getToken: function () {
                  return $cookieStore.get('token');
              }
          };
      });
  </code></pre>
  
  <p>Would it be right that I have to remove <code>$http</code> from it as it is being used by multiple services?
  am I understanding this concept correctly?</p>
  
  <p>[UPDATE#2]</p>
  
  <p>So, I updated my authintercepter and the auth service to this after @YOU suggested:</p>
  
  <pre><code>app.factory('authInterceptor', function ($rootScope, $location, $http, $q, $cookieStore, mvNotifier) {
          return {
              // Add authorization token to headers
              request: function (config) {
                  config.headers = config.headers || {};
                  if ($cookieStore.get('token')) {
                      config.headers.Authorization = 'Bearer ' + $cookieStore.get('token');
                  }
                  return config;
              },
  
              // Intercept 401s and redirect you to login
              responseError: function (response) {
                  if (response.status === 401) {
                      $location.path('/login');
                      // remove any stale tokens
                      mvNotifier.error("You don't have enough permissions for accessing this page. Please contact Site Admin for help", "Not Logged in!", true, true);
                      $cookieStore.remove('token');
                      return $q.reject(response);
                  }
                  else if (response.status === 403) {
                      $location.path('/login');
                      mvNotifier.error("You are forbidden from accessing this page. Please contact Site Admin for help.", "Access Forbidden", true, true);
                      $cookieStore.remove('token');
                      return $q.reject(response);
                  } else if(response.status === 405) {
                      $location.path('/');
                      $cookieStore.remove('token');
                      mvNotifier.error("Invalid/Missing Credentials!", "Please Try Logging in again!", false, false);
                  }
                  else {
                      return $q.reject(response);
                  }
              }
          };
      })
  </code></pre>
  
  <p>and my mvNotifier service is as follows - </p>
  
  <pre><code>angular.module('aarthikApp').service('mvNotifier', function (toastr) {
      this.warning = function (message, title, closeButton, progressBar) {
          toastr.warning(message, title, {
              closeButton: closeButton,
              progressBar: progressBar
          });
      };
      this.error = function (message, title, closeButton, progressBar) {
          toastr.error(message, title, {
              closeButton: closeButton,
              progressBar: progressBar
          });
      };
      this.success = function (message, title, closeButton, progressBar) {
          toastr.success(message, title, {
              closeButton: closeButton,
              progressBar: progressBar
          });
      };
  });
  </code></pre>
  
  <p>and the error I am getting now is - </p>
  
  <pre><code>Uncaught Error: [$injector:cdep] Circular dependency found: $http &lt;- authInterceptor &lt;- $http &lt;- Auth
  http://errors.angularjs.org/1.4.7/$injector/cdep?p0=%24http%20%3C-%20authInterceptor%20%3C-%20%24http%20%3C-%20Auth
  </code></pre>
  
  <p>[UPDATE#3]</p>
  
  <p>After removing $http from my auth interceptor I am getting the following error- </p>
  
  <pre><code>Uncaught Error: [$injector:cdep] Circular dependency found: $http &lt;- $templateRequest &lt;- $$animateQueue &lt;- $animate &lt;- toastr &lt;- mvNotifier &lt;- authInterceptor &lt;- $http &lt;- Auth
  </code></pre>