Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possibly unhandled rejection with Angular 1.5.9 #2889

Closed
skidvd opened this issue Jul 25, 2016 · 80 comments
Closed

Possibly unhandled rejection with Angular 1.5.9 #2889

skidvd opened this issue Jul 25, 2016 · 80 comments
Milestone

Comments

@skidvd
Copy link

skidvd commented Jul 25, 2016

When using ui-router v-0.2.18 and angularjs v-1.5.9 I keep getting this error 4 times:

Possibly unhandled rejection: {}
I was not getting this error with 1.4.x angular verisons, but am now that I have upgraded. Google searches are not turning up much related to this issue.

I also noticed this error shows up as soon as I insert the ui.router module.

@ave-sanket
Copy link

Same issue with me to using angular js v -1.5.9 and ui-router v-0.2.15.
Does reverting to 1.4.8 makes this go away?

@skidvd
Copy link
Author

skidvd commented Aug 2, 2016

Yes, in my case I was a 1.4.2 before attempting the 1.5 upgrade. Reverting to 1.4.x does make the error go away.

@lucax88x
Copy link

lucax88x commented Aug 4, 2016

happened the same upgrading from 1.5.8 to 1.5.9

this can be linked to #2699

anyway, a quick fix is to use this:

https://docs.angularjs.org/api/ng/provider/$qProvider

in order to set errorOnUnhandledRejections to false

@skidvd
Copy link
Author

skidvd commented Aug 5, 2016

@lucax88x, I attempting to apply the workaround you mentioned but not having any luck. Likely, I'm not understanding what you intend for me to do. Apologies if I am missing something obvious, but there does not appear to be useful examples of how to do this via google search.

I have modified my application's .run() function to call $q.errorOnUnhandledRejections(false); However, it keeps telling me that errorOnUnhandledRejections is not a function. Changing to .run() to literally set the value ($q.errorOnUnhandledRejections = false) succeeds (does not produce an error), but does not have any affect on the possibly unhandled rejection {} errors. Is it nor possible to make this change globally in the application? Do I need to do something to each and every time I access $q?

TIA!

@ghost
Copy link

ghost commented Aug 8, 2016

try $qProvider.errorOnUnhandledRejections(false)

@skidvd
Copy link
Author

skidvd commented Aug 8, 2016

@danivarga,

I'm sorry for the basic question, but I am missing something obvious. I have tried to inject $qProvider in both the typical manner - .run(['$qProvider', function($qProvider) {....}]); as well as via the $injector

$injector.invoke(['$qProvider', function($qProvider) {
    $qProvider.errorOnUnhandledRejections(false);
}]);

Both approaches result in Unknown Provided $qProviderProvider errors. Of course, without injecting a reference somehow, the $qProvider.errorOnUnhandledRejections(false) fails with an unknown $qProvider error.

I've also add 'ng' to my module list as well as attempted via the following approach, without success:

var $injector2 = window.angular.injector(['ng']);
$injector2.invoke(['$qProvider', function($qProvider) {
    $qProvider.errorOnUnhandledRejections(false);
}]);

How do I get a reference to this bad boy in my .run() function?

@christopherthielen
Copy link
Contributor

Not .run(), but rather .config()

@skidvd
Copy link
Author

skidvd commented Aug 8, 2016

@christopherthielen Of course, that makes more sense. Thank you!

Does anyone know if an official 'fix' for this issue is/will be worked, or is this the proper solution?

@HascourAdrien
Copy link

Would like to know aswell if the 1.5.9 will have this error unless we don t set to false the errorOnUnhandledRejections

@akholodenko
Copy link

akholodenko commented Nov 1, 2016

1.6.0-rc.0 has the same problem and is solved via the same workaround:

app.config(['$qProvider', function ($qProvider) {
    $qProvider.errorOnUnhandledRejections(false);
}]);

This error throwing ideally should be off by default and backward compatible.

@christopherthielen
Copy link
Contributor

This is fixed in 1.0 branch

@christopherthielen
Copy link
Contributor

closed by 66ab048

@cklemming
Copy link

cklemming commented Dec 2, 2016

I am getting this issue still with ui-router v-0.3.2 and angularjs v-1.6.0-rc.2. Specifically when closing UI Bootstrap modal dialogues (ui-bootstrap v-2.3.0). The $qProvider workaround resolves this.

@chm-dev
Copy link

chm-dev commented Dec 8, 2016

Same here 1.6.0

2 similar comments
@egamboa
Copy link

egamboa commented Dec 9, 2016

Same here 1.6.0

@gigmaps
Copy link

gigmaps commented Dec 9, 2016

Same here 1.6.0

@yukw777
Copy link

yukw777 commented Dec 9, 2016

Same here 1.6.0. Should be reopened.

@sirago
Copy link

sirago commented Dec 9, 2016

1.6 - same issue

@amalleIntesens
Copy link

Same here 1.6.0

@brentlemons
Copy link

I just moved from 1.5.8 to 1.6.0 and ui-router#1.0.0-beta.3 resolves the issue.

@markkesty
Copy link

I am using 1.6.0 and ui-router#1.0.0-beta.3 but now whenever I go to a route, it urlencodes the route so instead of getting a#/b/c I get a#%2Fb%2Fc and the navigation fails

@egamboa
Copy link

egamboa commented Dec 13, 2016

I got this error everytime I use .filter .forEach on some arrays.
extraRiders = rider.riders.filter(function (extraRider) { return extraRider.check });

as simple as this.

@zhangbg
Copy link

zhangbg commented Dec 13, 2016

Same here 1.6.0

@freeman29
Copy link

Same here I'm using 1.6.0 and 1.0.0-beta.3. some of my modal are not working because of this issue.

@swlee60
Copy link

swlee60 commented Dec 13, 2016

same here 1.6.0 and 0.3.2

@btk
Copy link

btk commented Dec 13, 2016

I had the same issue while using responsivevoice.js 3rd party app for those wants to track the problem.

https://gist.github.com/anchetaWern/ed6e841555602656e6ae

knalli added a commit to knalli/angular-vertxbus that referenced this issue Mar 7, 2017
@snehapvs
Copy link

seeing the issue again with angular 1.6.3 and ui router 0.4.2

@AdrienDC
Copy link

same here

@gorakhargosh
Copy link

Do the right thing. Debug your code and find the root of the problem and fix it. Don't mask the problem.

  • Brent Lemons

rm -rf angular.js

@christopherthielen
Copy link
Contributor

See also: #3404

@christopherthielen
Copy link
Contributor

1.0.4 is released

@AdrienDC
Copy link

AdrienDC commented Jun 12, 2017

Got some errors with 1.x.x: [object Object], <ion-nav-view class="view-container" nav-view-transition="none">

@dominik-mrugalski
Copy link

@christopherthielen
I'm using Angular 1.6.1 and i updated angular-ui-router to 1.0.4 but I still have "possibly unhandled rejection".

Could someone confirm that, 1.0.4 fix this problem ?
Hiding errors with errorOnUnhandledRejections() func isn't best solution....

tardyp added a commit to tardyp/buildbot that referenced this issue Jun 27, 2017
@aphairpq
Copy link

We are seeing this issue Angular 1.6.4 and angular-ui-router 1.0.4. I've been trying to hunt down any unhandled rejections on our end, but it seems to be getting rejected somewhere in the transition.

See the following log/trace:
image

Our onStart hook is basically checking if a user is authenticated or not. If not, it should redirect them to the login page (really simplified below):

$transitions.onStart({}, function(trans){
    if(needsAuthentication){
        return $state.target('login');
    }
});

@o-panikarovskiy
Copy link

o-panikarovskiy commented Jul 1, 2017

$provide.decorator("$exceptionHandler", ["$delegate", function ($delegate) {
    return function (exception, cause) {
        if (!cause) return; //do nothing (ignore) exception in this case === 'Possibly unhandled rejection: undefined'               
        $delegate(exception, cause);
    };
}]);

works for me.

@andreaslarssen
Copy link

Got the same block as @aphairpq:

$transitions.onStart({to: 'authentication.login'}, function (trans) {
      var $auth = trans.injector().get('$auth');
      var $state = trans.router.stateService;

      if ($auth.isAuthenticated()) {
        return $state.target('user.settings.profile');
      }
    });

It throws the "Possibly unhandled rejection: {"$id":0,"type":2,"message":"The transition has been superseded by a different transition"...... error

Followed the q decorator tip above to get the trace, and toCheck.stack shows:

"Error
    at Promise.set [as $$state] (http://localhost:9000/scripts/qDecorator.js:17:21)
    at new Promise (http://localhost:9000/bower_components/angular/angular.js:16789:18)
    at Promise.then (http://localhost:9000/bower_components/angular/angular.js:16797:20)
    at Promise.finally (http://localhost:9000/bower_components/angular/angular.js:16811:19)
    at http://localhost:9000/scripts/config/ui-router.js:70:28
    at invokeCallback (http://localhost:9000/bower_components/angular-ui-router/release/angular-ui-router.js:1545:34)
    at TransitionHook.invokeHook (http://localhost:9000/bower_components/angular-ui-router/release/angular-ui-router.js:1557:26)
    at http://localhost:9000/bower_components/angular-ui-router/release/angular-ui-router.js:1649:60
    at processQueue (http://localhost:9000/bower_components/angular/angular.js:16832:37)
    at http://localhost:9000/bower_components/angular/angular.js:16876:27"

According to the docs, returning a target state, the router should redirect, and it does. It's just that annoying error message floods the console every time. Even tried to return a promise, just for the hell of it. Same result:

$transitions.onStart({to: 'authentication.login'}, function (trans) {
      var $auth = trans.injector().get('$auth');
      var $state = trans.router.stateService;

      if ($auth.isAuthenticated()) {
        var $q = trans.injector().get('$q');
        var def = $q.defer();
        def.resolve($state.target('user.settings.profile'));
        return def.promise;
      }
    });

I can't see that there are other state's being initiated, no other hooks are in play and generally nothing to indicate that this should not work.

Silencing the errors is not an option.

ui-router 1.0.6
angular 1.6.4

@tiagomsmagalhaes
Copy link

I think I also have a similar issue as @aphairpq and @andreaslarssen

runtimeFunction.$inject = ['$transitions', '$trace', 'AuthService'];
  function runtimeFunction($transitions, $trace, AuthService) {
    $trace.enable('TRANSITION');
    $transitions.onStart( { to: 'dashboard' }, function(trans) {
      var $state      = trans.router.stateService;
      var AuthService = trans.injector().get('AuthService');

      AuthService.getUserStatus().then(function (res) {if (!res.data.status) $state.transitionTo("index")})
    });

  }
/*

Log
Transition #0-0: Started  -> "Transition#0( ''{} -> 'dashboard'{} )"
trace.ts:153 Transition #1-0: Started  -> "Transition#1( ''{} -> 'index'{} )"
trace.ts:192 Transition #0-0: <- Rejected "Transition#0( ''{} -> 'dashboard'{} )", reason: Transition Rejection($id: 0 type: 2, message: The transition has been superseded by a different transition, detail: Transition#1( ''{} -> 'index'{} ))
stateService.ts:525 Transition Rejection($id: 0 type: 2, message: The transition has been superseded by a different transition, detail: Transition#1( ''{} -> 'index'{} ))
_defaultErrorHandler @ stateService.ts:525
(anonymous) @ stateService.ts:365
processQueue @ angular.js:17000
(anonymous) @ angular.js:17044
$digest @ angular.js:18182
$apply @ angular.js:18480
done @ angular.js:12501
completeRequest @ angular.js:12727
requestLoaded @ angular.js:12655
XMLHttpRequest.send (async)
(anonymous) @ angular.js:12701
sendReq @ angular.js:12446
serverRequest @ angular.js:12198
processQueue @ angular.js:17000
(anonymous) @ angular.js:17044
$digest @ angular.js:18182
$apply @ angular.js:18480
bootstrapApply @ angular.js:1952
invoke @ angular.js:5040
doBootstrap @ angular.js:1950
bootstrap @ angular.js:1970
angularInit @ angular.js:1855
(anonymous) @ angular.js:33826
trigger @ angular.js:3468
trace.ts:198 Transition #1-0: <- Success  "Transition#1( ''{} -> 'index'{} )", final state: index

I enabled to trace with the decorator made by @christopherthielen I'm not seing the issue.

I have angular 1.6.5 and ui-router 1.0.3

@andreaslarssen
Copy link

Do you have some wisdom to share, @christopherthielen?

@christopherthielen
Copy link
Contributor

@aphairpq this is a very late response, but I was unable to reproduce your scenario as described:

http://plnkr.co/edit/JAuapA2wtq7vd72imizF?p=preview

@christopherthielen
Copy link
Contributor

christopherthielen commented Oct 21, 2017

@andreaslarssen what is defined in the hook inside http://localhost:9000/scripts/config/ui-router.js:70:28?

Your stack trace suggests that the .catch block should be added to that hook, either inside the finally handler or possibly chained after it.

    at Promise.set [as $$state] (http://localhost:9000/scripts/qDecorator.js:17:21)
    at new Promise (http://localhost:9000/bower_components/angular/angular.js:16789:18)
    at Promise.then (http://localhost:9000/bower_components/angular/angular.js:16797:20)
    at Promise.finally (http://localhost:9000/bower_components/angular/angular.js:16811:19)
    at http://localhost:9000/scripts/config/ui-router.js:70:28

@christopherthielen
Copy link
Contributor

christopherthielen commented Oct 21, 2017

@tiagomsmagalhaes try using a redirect instead:

  runtimeFunction.$inject = ['$transitions', '$trace', 'AuthService'];
  function runtimeFunction($transitions, $trace, AuthService) {
    $trace.enable('TRANSITION');
    $transitions.onStart( { to: 'dashboard' }, function(trans) {
      var $state      = trans.router.stateService;
      var AuthService = trans.injector().get('AuthService');

      return AuthService.getUserStatus()
        .then(function (res) {
          if (!res.data.status) 
            return $state.target("index");
         })
    });
  }

@christopherthielen
Copy link
Contributor

christopherthielen commented Oct 21, 2017

I updated the q decorator such that it prints out the unhandled rejections stack traces to the console. It only works if you are not using minification (because it parses the stack traces). Also I only tried it with Chrome.

http://plnkr.co/edit/GGVhS6gcxFDi0es36109?p=preview

// Decorate the $q service when app starts
angular.module('qDecorator', [])
.decorator('$q', ['$delegate', function($delegate) {
  // Create a sample promise.
  var promise = $delegate.when();

  // Access the `Promise` prototype (nonstandard, but works)
  var promisePrototoype = promise.__proto__;
  var isPromisePrototype = typeof promisePrototoype === 'object' &&
    ['then', 'catch', 'finally'].reduce(function(acc, key) { 
      return acc && !!promisePrototoype[key]; 
    }, true);

  if (isPromisePrototype) {
    // The angular $q promise implementation sets `$$state` once in its Promise varructor:
    //
    // function Promise() {
    //   this.$$state = { status: 0 };
    // }
    //
    // Hijack the promise behavior by adding a setter for `$$state` on the Promise prototype.
    // The setter is run each time a promise is created (via any method: $q.when(), promise.then(), etc).
    //
    // The setter records the stack trace in which the promise was created.
    Object.defineProperty(promisePrototoype, '$$state', {
      set: function($$state) {
        this._$$state = $$state;

        if (typeof $$state._status === 'undefined') {
          this._value = this.value;
          this._logged = false;

          // Define a getter for `Promise.$$state.value`
          // ('value' is the resolved or rejected value)
          Object.defineProperty($$state, 'value', {
            enumerable: true,
            set: function(val) {
              this._value = val;
            },
            get: function() {
              // Check if this is the "Possibly unhandled rejection" handler. return the stack trace instead
              if (this.status === 2 && this.pur && new Error().stack.includes('processChecks')) {
                if (!this._logged) {
                  this._logged = true;
                  console.error(this._value)
                }
                return this._context; 
              }
              return this._value;
            },
          });
        }

        // Create an Error object and use its stack trace
        $$state._context = new Error('Possibly unhandled rejection (promise creation stack)');
      },
      get: function() {
        return this._$$state;
      },
      enumerable: true,
    });

    // Whenever promise.then() (or .catch or .finally) is called, a new promise is created.
    // Add the chained-from-promise's stack to the new promise's stack to allow analysis of the full promise chain
    var realThenFn = promisePrototoype.then;
    promisePrototoype.then = function() {
      var chainedPromise = realThenFn.apply(this, arguments);

      var prevContext = this.$$state && this.$$state._context;
      var chainedContext = chainedPromise.$$state && chainedPromise.$$state._context;

      if (chainedContext) {
        try {
          chainedContext.stack =  chainedContext.stack +
            '\nPromise Chained from:\n' +
            prevContext.stack;
        } catch (ignored) {}
      }
      return chainedPromise;
    }
  }

  return $delegate;
}]);

@andreaslarssen
Copy link

andreaslarssen commented Oct 23, 2017

@christopherthielen: Holy cow, you're right! Was using the finally handler to remove a loading screen.

Good catch (pun intended), thanks!

@yosiasz
Copy link

yosiasz commented Oct 31, 2017

This was my issue in case it helps someone else. It had nothing to do with ui-router, well at least as far as I can see, maybe a red herring.

        .module('app.risk')
        .run(appRun);

    /* @ngInject */
    function appRun(routerHelper) {
        routerHelper.configureStates(getStates());
    }

    function getStates() {...

I had another method called getStates and there was collision with this getStates router. :(

dutoitc pushed a commit to dutoitc/copper that referenced this issue Nov 6, 2017
@adamreisnz
Copy link

adamreisnz commented May 11, 2018

// The angular $q promise implementation sets $$state once in its Promise varructor:

Just wanted to highlight this gem of a find & replace fail (const to var), varructor 😆

And on a more constructive note; I was running into this unhandled rejection issue on account of routes not resolving due to 401 errors for asynchronous resolves.

However, we handle those 401's elsewhere and try to refresh the user's session in that case, so an error is not necessary. Yet UI router throws these exceptions and they are then caught in the global exception handler.

So to address this, we filter them out in the exception handler decorator:

//Exception handling
  $provide.decorator('$exceptionHandler', [
    '$log', 'Raven',
    function($log, Raven) {
      return (exception, cause) => {

        //No cause, ignore unhandled rejection warnings for undefined
        if (!cause) {
          return;
        }

        //UI router non authenticated errors
        if (
          typeof cause === 'object' &&
          typeof cause.detail === 'object' &&
          cause.message === `The transition errored` &&
          cause.detail.status === 401
        ) {
          return;
        }

        //Capture exception and log
        Raven.captureException(exception);
        $log.error(exception);
      };
    }]);

@stale
Copy link

stale bot commented Jan 24, 2020

This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs.

This does not mean that the issue is invalid. Valid issues
may be reopened.

Thank you for your contributions.

@stale stale bot added the stale label Jan 24, 2020
@stale stale bot closed this as completed Feb 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests