Angular 1.6.0: "Possibly unhandled rejection" error

120,892

Solution 1

Try adding this code to your config. I had a similar issue once, and this workaround did the trick.

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

Solution 2

The code you show will handle a rejection that occurs before the call to .then. In such situation, the 2nd callback you pass to .then will be called, and the rejection will be handled.

However, when the promise on which you call .then is successful, it calls the 1st callback. If this callback throws an exception or returns a rejected promise, this resulting rejection will not be handled, because the 2nd callback does not handle rejections in cause by the 1st. This is just how promise implementations compliant with the Promises/A+ specification work, and Angular promises are compliant.

You can illustrate this with the following code:

function handle(p) {
    p.then(
        () => {
            // This is never caught.
            throw new Error("bar");
        },
        (err) => {
            console.log("rejected with", err);
        });
}

handle(Promise.resolve(1));
// We do catch this rejection.
handle(Promise.reject(new Error("foo")));

If you run it in Node, which also conforms to Promises/A+, you get:

rejected with Error: foo
    at Object.<anonymous> (/tmp/t10/test.js:12:23)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.runMain (module.js:604:10)
    at run (bootstrap_node.js:394:7)
    at startup (bootstrap_node.js:149:9)
    at bootstrap_node.js:509:3
(node:17426) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: bar

Solution 3

The first option is simply to hide an error with disabling it by configuring errorOnUnhandledRejections in $qProvider configuration as suggested Cengkuru Michael

BUT this will only switch off logging. The error itself will remain

The better solution in this case will be - handling a rejection with .catch(fn) method:

resource.get().$promise
    .then(function (response) {})
    .catch(function (err) {});

LINKS:

Solution 4

Found the issue by rolling back to Angular 1.5.9 and rerunning the test. It was a simple injection issue but Angular 1.6.0 superseded this by throwing the "Possibly Unhandled Rejection" error instead, obfuscating the actual error.

Solution 5

To avoid having to type additional .catch(function () {}) in your code in multiple places, you could add a decorator to the $exceptionHandler.

This is a more verbose option than the others but you only have to make the change in one place.

angular
    .module('app')
    .config(configDecorators);

configDecorators.$inject = ["$provide"];
function configDecorators($provide) {

    $provide.decorator("$exceptionHandler", exceptionHandler);

    exceptionHandler.$inject = ['$delegate', '$injector'];
    function exceptionHandler($delegate, $injector) {
        return function (exception, cause) {

            if ((exception.toString().toLowerCase()).includes("Possibly unhandled rejection".toLowerCase())) {
                console.log(exception); /* optional to log the "Possibly unhandled rejection" */
                return;
            }
            $delegate(exception, cause);
        };
    }
};
Share:
120,892
Groucho
Author by

Groucho

Updated on July 05, 2022

Comments

  • Groucho
    Groucho almost 2 years

    We have a pattern for resolving promises in our Angular app that has served us well up until Angular 1.6.0:

        resource.get().$promise
            .then(function (response) {
            // do something with the response
            }, function (error) {
                // pass the error the the error service
                return errorService.handleError(error);
            });
    

    And here is how we are triggering the error in Karma:

        resourceMock.get = function () {
            var deferred = $q.defer();
            deferred.reject(error);
            return { $promise: deferred.promise };
        };
    

    Now, with the update to 1.6.0, Angular is suddenly complaining in our unit tests (in Karma) for rejected promises with a "Possibly unhandled rejection" error. But we are handling the rejection in the second function that calls our error service.

    What exactly is Angular looking for here? How does it want us to "handle" the rejection?

  • Groucho
    Groucho over 7 years
    Good points! Yes, the intent is to handle rejection that occurs before the call to .then. The code that is triggering this rejection (and which worked for Angular 1.5.9) has been added to the original question.
  • vip
    vip over 7 years
    How to actually fix asked pattern code?
  • vip
    vip over 7 years
    Ok, fix is like $promise.then(success).catch(error), where catch catches all errors, more in "Note" section at migration
  • ChrisJ
    ChrisJ about 7 years
    This is a big problem for me currently as I'm migrating a code base and replacing an old injected dependency. Did you find a way to prevent that obfuscation and get it to throw the real error?
  • Groucho
    Groucho about 7 years
    The top answer above will fix it in running code, but I couldn't get it to throw the error in Karma without rolling back to Angular 1.5.9.
  • Daniel Bonnell
    Daniel Bonnell about 7 years
    Still getting this in 1.6.2
  • Sachin Sharma
    Sachin Sharma almost 7 years
    I must point out that this merely hides the error, according to developers there is some issue in code,and it just masks the error.
  • Skrew
    Skrew over 6 years
    Agree, while it may shun the issue the root cause remains and the developer should handle error case instead.
  • Mostafa Berg
    Mostafa Berg over 6 years
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review
  • Piotr Pradzynski
    Piotr Pradzynski over 6 years
    @MostafaTorbjørnBerg thanks. I updated the answer.
  • tcmoore
    tcmoore over 6 years
    this really should be the correct answer
  • Ryan Silva
    Ryan Silva about 6 years
    What if your function returns a rejected promise by design? Similar to the way $http.get() returns a promise that by design is rejected if the request fails. I have functions which return promises, and in certain cases they can return $q.reject(err), it seems that angular doesn't like this unless I clobber the warnings?
  • Hobbamok
    Hobbamok over 5 years
    What config file specifically?