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

Random "Cannot read property 'params' of undefined" errors #2327

Closed
pocesar opened this issue Oct 22, 2015 · 18 comments
Closed

Random "Cannot read property 'params' of undefined" errors #2327

pocesar opened this issue Oct 22, 2015 · 18 comments

Comments

@pocesar
Copy link

pocesar commented Oct 22, 2015

My client side analytics is getting filled with the same errors that seems to be related to ui-router

TypeError Cannot read property 'params' of undefined (inheritParams > js:2245)  

TypeError Cannot read property 'params' of undefined <a analytics="click" analytics-category="'login'" analytics-label="'criar'" ui-sref="login.index.criar"> (inheritParams > js:2245)

TypeError Cannot read property 'params' of undefined <a class="header-menu-item" ui-sref-active="selected" analytics="click" analytics-category="'login'" analytics-label="'criar'" ui-sref="login.index.criar"> (inheritParams > js:2245)

TypeError Cannot read property 'params' of undefined <a class="header-menu-item" ui-sref-active="selected" analytics="click" analytics-category="'login'" analytics-label="'entrar'" ui-sref="login.index.login"> (inheritParams > js:2245)

TypeError Cannot read property 'params' of undefined <a ng-repeat="item in menu track by $index" ui-sref-active="selected" ng-attr-ui-sref="{{ :: item.sref }}" class="square header-menu-item header-main-item" ng-bind=" :: item.name"> (inheritParams > js:2245)

TypeError Cannot read property 'params' of undefined <a ui-sref-active="selected" ng-attr-ui-sref="{{ :: item.sref }}" ng-bind=" :: item.name"> (inheritParams > js:2245)   

TypeError Cannot read property 'params' of undefined <a ui-sref="user.coupons.ativos" ui-sref-active="selected" analytics="click" analytics-category="'mobile-logged-dropdown'" analytics-label="'coupons'"> (inheritParams > js:2245)

TypeError Cannot read property 'params' of undefined <a ui-sref="user.profile" ui-sref-active="selected" analytics="click" analytics-category="'mobile-logged-dropdown'" analytics-label="'profile'"> (inheritParams > js:2245)

TypeError Cannot read property 'params' of undefined <button class="btn nav-fixed-btn btn-primary btn-smaller" analytics="click" analytics-category="'login'" analytics-label="'entrar'" ui-sref="login.index.login"> (inheritParams > js:2245)

TypeError Cannot read property 'params' of undefined <img ui-sref="index" src="/content/clients/wsf/logo.svg"> (inheritParams > js:2245)
            $stateProvider.state('login', {
                url: '/login',
                abstract: true,
                template: '<div ui-view></div>'
            });

            $stateProvider.state('login.index', {
                url: '/',
                abstract: true,
                templateUrl: '/templates/boxes/login',
                controller: Controllers.Login,
                controllerAs: 'login'
            });

            $stateProvider.state('login.index.login', {
                url: '',
                views: {
                    'inner': {
                        templateUrl: '/templates/boxes/cadastrado'
                    }
                }
            });

            $stateProvider.state('login.index.criar', {
                url: 'criar',
                views: {
                    'inner': {
                        templateUrl: '/templates/boxes/criar'
                    }
                }
            });

            $stateProvider.state('user', {
                abstract: true,
                url: '/user',
                template: '<div ui-view></div>',
                data: {
                    allowed: true
                }
            });

            $stateProvider.state('user.profile', {
                url: '/profile',
                templateUrl: '/templates/partials/user/index'
            });

            $stateProvider.state('user.coupons', {
                url: '/coupons', 
                templateUrl: '/templates/partials/user/coupons'
            });

            $stateProvider.state('user.coupons.ativos', {
                url: '/ativos',
                views: {
                    'tables': {
                        templateUrl: '/templates/partials/user/ativos'
                    }
                }
            });

I can't reproduce this on local machine, so I'm a little stumped

@eddiemonge
Copy link
Contributor

Can you find where the error is being thrown as I'm not sure what the trace is showing

@shonatodc
Copy link

What's in "Controllers.Login"? And which view does this error occur in, because it looks like whatever is going on, there's a "params" property not being set, or failed to set.

@pocesar
Copy link
Author

pocesar commented Oct 26, 2015

@shonatodc it's a controller wrapper around the Login service (that holds current user access tokens). nothing related to $state or $stateParams

@eddiemonge the exception on Google Analytics only accept 255 chars of information, that's why there isn't a complete stacktrace. Since I couldn't reproduce locally, I assume the inheritParams is trying to merge the params from the current state, but it's undefined (aka, no data defined)?

@eddiemonge
Copy link
Contributor

Its hard to tell but it seems like there is a call to a ???.params where the ??? isn't a valid object or a correct reference isn't being made somehow

@mrzepinski
Copy link

I have the same problem. It occurs in inheritParams (common.js) function on line:
if (!parents[i].params) continue;

parents[i] is undefined randomly

It occurs when I use $state.href function to generate URL to the correct state with params.

FYI: @eddiemonge

@eddiemonge
Copy link
Contributor

It occurs when I use $state.href function to generate URL to the correct state with params.

Can you do a plnkr showing that or what you mean by that?

@mrzepinski
Copy link

@eddiemonge It's simple use case. I want to create URL in my controller to the state with some params. When I use $state.href function to do that, it invokes inheritParams to merge default ui.router params with my state params which I passed to $state.href.

In that case, I got Cannot read property 'params' of undefined randomly and execution stops on if (!parents[i].params) continue; statement. parents[i] is undefined.

I didn't get that error when I debugged my code. It occurs on production.

I think that we should add some checking here or create parents array in another way.

@pocesar
Copy link
Author

pocesar commented Oct 29, 2015

@mrzepinski I think it's a race condition, while the iteration of parents is happening, the transition of routes mutates the array at the same time, making the parents[i] at that time undefined (but was certainly there before)
I guess the simplest fix would to change

if (!parents[i].params) continue;
to be if (!parents[i] || !parents[i].params) continue;

@rickyrobinson
Copy link

@pocesar Did you submit a PR for your suggested fix above? We're seeing exactly the same issue in our app occasionally, usually traced to an element with ui-sref.

Might just be a fluke, but so far these "TypeError Cannot read property 'params' of undefined" errors in our log are always when user is on Chrome on Windows. I haven't been able to trigger this problem with Chrome on my Mac. At first I thought it was isolated to Chrome 46.0.2490.80 on Windows, but going further back in the logs I see the same error occurring on older versions of Chrome (but always on Windows).

@pocesar
Copy link
Author

pocesar commented Nov 2, 2015

@rickyrobinson I didn't yet, I was reading the source trying to pinpoint the problem. AFAIK the directives seems to be using a modified version of the object that gets passed to the service, and that might be generating the race condition (on calls to $state.href)

@arcmode
Copy link

arcmode commented Nov 6, 2015

@pocesar I found what was triggering the issue in my case. Hope it can help others.

Turns out in my case it was being triggered by a workaround I had to wrote because Prototype.js was messing with Array.prototype.toJSON. Since I can't drop Prototype because my code runs on arbitrary websites as a widget I solved the issue (on our website) narrowing the workaround by checking if the "bad" version of Prototype is present.

Previously I had this:

var _json_stringify = JSON.stringify;
JSON.stringify = function(value) {
  var _array_tojson = Array.prototype.toJSON;
  delete Array.prototype.toJSON;
  var r=_json_stringify(value);
  Array.prototype.toJSON = _array_tojson;
  return r;
};

Now I have this

if ('object' === typeof window.Prototype) {
    var PrototypeVersion = window.Prototype.Version.split('.');
    if (parseInt(PrototypeVersion[0], 10) > 1) return;
    if (parseInt(PrototypeVersion[1], 10) > 6) return;
    if (parseInt(PrototypeVersion[2], 10) > 1) return;
    var _json_stringify = JSON.stringify;
    JSON.stringify = function(value) {
       var _array_tojson = Array.prototype.toJSON;
       delete Array.prototype.toJSON;
       var r=_json_stringify(value);
       Array.prototype.toJSON = _array_tojson;
       return r;
    };
}

By doing this our app does not suffer from this issue anymore (we don't use Prototype). But anyone using ui.router and messing with Array.prototype will probably suffer from it until the PR that solves it for good gets merged.

@HadrienPierart
Copy link

I also see that kind of behavour, but for some reason, Im thinking that it could be linked with some libs Im using in my app : JSON3 and ES5-shim which indeed manipulate the prototype of Array...

@cferriss
Copy link

+1
Experiencing this issue in production environment as well, traced to:

if (!parents[i].params) continue;

if (!parents[i].params) continue;

@ramondeklein
Copy link

We experience this issue on our website too. Never seen this issue in development, but pops up in production sometimes. Always triggered by a call to $state.href or $state.go. Traced back to the same line of code as described above...

@eddiemonge
Copy link
Contributor

again, it would be helpful if someone can make a plnkr demonstrating this so

@ramondeklein
Copy link

I would love to create a Plunkr, but the weird thing is that I never encounter this issue myself, but some of our users seem to be affected by it.

piotrd pushed a commit to piotrd/ui-router that referenced this issue Jan 22, 2016
@piotrd
Copy link

piotrd commented Jan 22, 2016

This error is currently one of the top 3 of our most commonly logged errors. It has occurred hundreds of times in our app on production, but I have never managed to reproduce it myself neither on production nor locally, so it's really not a matter of us not willing to create a Plunkr ;)

Summing up observations:

  • only on production environment

  • the error occurs no matter if I use Angular 1.3.x or 1.4.x

  • the error occurs to people using Windows 7, 8, 8.1, 10 as well as MacOSX 10.10.5 in any browsers like Chrome 31-48, Opera 34 or even Maxthon 4.4.7 (so it looks like Webkit browsers), but also on IE11@Windows 8.1

  • we are not using $state.href anywhere in our code, but we are using $state.go and $state.transitionTo

  • all stacktraces end up with this line if (!parents[i].params) continue;, and here are some of them:

    TypeError: Cannot read property 'params' of undefined
    1 File "node_modules/angular-ui-router/release/angular-ui-router.js" line 112 col 1 in g
    if (!parents[i].params) continue;
    2 File "node_modules/angular-ui-router/release/angular-ui-router.js" line 3147 col 1 in Object.B
    if (options.inherit) toParams = inheritParams($stateParams, toParams || {}, $state.$current...
    3 File "node_modules/angular-ui-router/release/angular-ui-router.js" line 3071 col 1 in Object.N
    return $state.transitionTo(to, params, extend({ inherit: true, relative: $state.$current },...
    4 File "node_modules/angular-ui-router/release/angular-ui-router.js" line 4184 col 1 in [anonymous]
    $state.go(ref.state, params, options);
    5 File "bower_components/angular/angular.js" line 16380 col 28 in [anonymous]
    deferred.resolve(fn());
    6 File "bower_components/angular/angular.js" line 4940 col 10 in m
    fn.apply(null, sliceArgs(arguments, 1));
    7 File "bower_components/angular/angular.js" line 5328 col 7 in [anonymous]
    completeOutstandingRequest(fn);
    TypeError: Cannot read property 'params' of undefined
    1 File "node_modules/angular-ui-router/release/angular-ui-router.js" line 112 col 1 in g
    if (!parents[i].params) continue;
    2 File "node_modules/angular-ui-router/release/angular-ui-router.js" line 3147 col 1 in Object.B [as transitionTo]
    if (options.inherit) toParams = inheritParams($stateParams, toParams || {}, $state.$current...
    3 File "app/scripts/controllers/navigation.coffee" line 104 col 12 in m
    $state.transitionTo($state.current, params, {reload: true, inherit: true, notify: true}).then ->
    4 File "app/scripts/controllers/navigation.coffee" line 120 col 7 in [anonymous]
    updateView(business)
    5 File "node_modules/angular/angular.js" line 14792 col 1 in l
    deferred.resolve(fn(state.value));
    6 File "node_modules/angular/angular.js" line 14808 col 1 in [anonymous]
    nextTick(function() { processQueue(state); });
    7 File "node_modules/angular/angular.js" line 16052 col 1 in p.$eval
    return $parse(expr)(this, locals);
    8 File "node_modules/angular/angular.js" line 15870 col 1 in p.$digest
    asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals);
    9 File "node_modules/angular/angular.js" line 16160 col 1 in p.$apply
    $rootScope.$digest();
    10 File "node_modules/angular-touch/angular-touch.js" line 477 col 1 in HTMLDivElement.<anonymous>
    scope.$apply(function() {
    TypeError: Cannot read property 'params' of undefined
    1 File "node_modules/angular-ui-router/release/angular-ui-router.js" line 112 col 1 in g
    if (!parents[i].params) continue;
    2 File "node_modules/angular-ui-router/release/angular-ui-router.js" line 3501 col 1 in Object.H [as href]
    if (options.inherit) params = inheritParams($stateParams, params || {}, $state.$current, st...
    3 File "node_modules/angular-ui-router/release/angular-ui-router.js" line 4156 col 1 in _
    newHref = $state.href(ref.state, params, options);
    4 File "node_modules/angular-ui-router/release/angular-ui-router.js" line 4171 col 1 in Object.fn
    if (newVal !== params) update(newVal);
    5 File "node_modules/angular/angular.js" line 15896 col 1 in p.$digest
    watch.fn(value, ((last === initWatchVal) ? value : last), current);
    6 File "node_modules/angular/angular.js" line 16160 col 1 in p.$apply
    $rootScope.$digest();
    7 File "node_modules/angular/angular.js" line 10589 col 1 in b
    if (!$rootScope.$$phase) $rootScope.$apply();
    8 File "node_modules/angular/angular.js" line 10787 col 1 in w
    callback(status, response, headersString, statusText);
    9 File "node_modules/angular/angular.js" line 10728 col 1 in XMLHttpRequest.$
    completeRequest(callback,
    10 File "<anonymous>" line 23 col 211 in XMLHttpRequest.h

Solution from #2327 (comment) is what I came up with as well. Would it break anything if this change was merged in? I would not like to keep a fork just for this single line of code...

@nateabele
Copy link
Contributor

@piotrd That's weird. Sure, submit a PR.

piotrd pushed a commit to piotrd/ui-router that referenced this issue Jan 22, 2016
christopherthielen added a commit that referenced this issue Jan 24, 2016
fix(common.js): "Cannot read property 'params' of undefined" errors
Closes #2327
ExpFront pushed a commit to ExpFront/ui-router that referenced this issue Jun 23, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests