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

Router: Cannot read property '_outlets' of undefined #12634

Closed
JohannesRudolph opened this Issue Oct 31, 2016 · 13 comments

Comments

Projects
None yet
9 participants
@JohannesRudolph

JohannesRudolph commented Oct 31, 2016

I'm submitting a ... (check one with "x")

[x] bug report => search github for a similar issue or PR before submitting

Current behavior
When switching routes I sometimes get the following error thrown by the router

error_handler.js:47 EXCEPTION: Uncaught (in promise): TypeError: Cannot read property '_outlets' of undefined
TypeError: Cannot read property '_outlets' of undefined
    at http://localhost:4200/main.bundle.js:14278:56
    at forEach (http://localhost:4200/main.bundle.js:5901:13)
    at PreActivation.deactiveRouteAndItsChildren (http://localhost:4200/main.bundle.js:14277:99)
    at http://localhost:4200/main.bundle.js:14279:19
    at forEach (http://localhost:4200/main.bundle.js:5901:13)
    at PreActivation.deactiveRouteAndItsChildren (http://localhost:4200/main.bundle.js:14277:99)
    at PreActivation.traverseRoutes (http://localhost:4200/main.bundle.js:14262:22)
    at http://localhost:4200/main.bundle.js:14233:19
    at Array.forEach (native)
    at PreActivation.traverseChildRoutes (http://localhost:4200/main.bundle.js:14232:29)

Digging the source, it looks like there's a null reference check missing for outlet.outletMap here:

    PreActivation.prototype.deactiveRouteAndItsChildren = function (route, outlet) {
        var _this = this;
        var prevChildren = nodeChildrenAsMap(route);
        __webpack_require .... function (v, k) {
            var childOutlet = outlet ? outlet.outletMap._outlets[k] : null;
            _this.deactiveRouteAndItsChildren(v, childOutlet);

Expected behavior
Uh, navigate without error!

Minimal reproduction of the problem with instructions
Unfortunately not yet a minimum repro, but my routing configuration looks like this:

export const ROUTES: Route[] = [
  { path: '', redirectTo: 'home', pathMatch: 'full' },

  // eagerly loaded modules
  { path: 'home', component: HomeComponent },
  // global modules
  { path: 'profile', loadChildren: 'app/profile/profile.module#ProfileModule', canLoad: [AuthGuard] },
  // service modules
  {
    path: 'locations/:locationTag',
    canActivateChild: [AuthGuard],
    resolve: {
      session: SessionResolveGuard
    },
    children: [
      { path: 'child', loadChildren: 'app/child/child.module#ChildModule' },
    ]
  },
  { path: '**', component: NoContentComponent }
];

The error occurs when navigating from ChildModule /locations/xyz/child to the /profile route.

Please tell us about your environment:
angular-cli: 1.0.0-beta.19-3
node: 6.3.0
os: darwin x64

  • Angular version: 2.1.2
    router version "3.1.2"

  • Browser:
    all

  • Language:
    TypeScript 2.0.3

  • Node (for AoT issues): node --version =
    node: 6.3.0

@DzmitryShylovich

This comment has been minimized.

Contributor

DzmitryShylovich commented Oct 31, 2016

Pls add a minimal working repro in plunkr.

@tomastrajan

This comment has been minimized.

tomastrajan commented Oct 31, 2016

Having the same problem, happens when I am trying to navigate away from component-less route with path: ""

@AlexMesser

This comment has been minimized.

AlexMesser commented Nov 1, 2016

have the same issue after yeasterdays update to latest angular version

@JohannesRudolph

This comment has been minimized.

JohannesRudolph commented Nov 1, 2016

I can confirm that downgrading the router to 3.1.1 (leaving everything else intact, i.e. angular 2.1.2 with router 3.1.1) fixes the issue for me. Thanks @AlexMesser

Hence it appears this is a regression which should be fixed ASAP @DzmitryShylovich .

Repro: http://plnkr.co/edit/HSq837Eor1HQw2lkCO2V
Steps: Click "Crisis Center", click "login" button at bottom. Click "Heroes" => error logged to console. The issue appears to depend on the presence of the "canActivateChild" guard on the locations/:locationTag route.

I was also able to reproduce a related issue ("Cannot read property 'canDeactivate' of null") in this modified tour of heroes example: http://plnkr.co/edit/ZpuYNYuRcug7etzA0TiR
Steps: Click "crisis center", click "login", select a crisis, click "Heroes" tab => error logged to console.

@DzmitryShylovich

This comment has been minimized.

Contributor

DzmitryShylovich commented Nov 1, 2016

There was a commit after 2.1.2 release.
Can u test it with the latest router version "@angular/router": "github:angular/router-builds",?

@JohannesRudolph

This comment has been minimized.

JohannesRudolph commented Nov 1, 2016

@DzmitryShylovich can't test it in plunkr, apparently I get a CORS error from github. What's the system.js config I'd need to pass in? In any case, it's probably trivial for you to try it yourself.

@JohannesRudolph

This comment has been minimized.

JohannesRudolph commented Nov 1, 2016

I couldn't get the router-builds repo to work in plunkr, but in my local code base. Using
"@angular/router": "github:angular/router-builds#3e49c54a1006c5b7b26c606092c490ee6ca36c58" in my package.json I have stopped seeing the error message about missing _outlets. However, it's now no longer navigating from a lazy loaded child route to a top-level lazy loaded route at all, with no error message logged 👎

@JohannesRudolph

This comment has been minimized.

JohannesRudolph commented Nov 1, 2016

Forget what I just said, using the version specified above still produces the exact some error, but does no longer log it to console, wtf!?

Registering a navigation event listener, I see this:
app.component.ts:44 NavigationError(id: 13, url: '/profile', error: TypeError: Cannot read property '_outlets' of undefined)

@nappynapster

This comment has been minimized.

nappynapster commented Nov 2, 2016

I have the same error but I only get this error when I build my code in productive mode. In development mode everything works fine.

Shpiller pushed a commit to Shpiller/angular that referenced this issue Nov 3, 2016

Shpiller pushed a commit to Shpiller/angular that referenced this issue Nov 3, 2016

Алексей Решетников
fix(router): check that outlet.outletMap exists before you access it
without this check periodically, an error occurs as described in angular#12634
@JohannesRudolph

This comment has been minimized.

JohannesRudolph commented Nov 15, 2016

I believe this is fixed in v2.2.0 of angular (router 3.2.0 respectively).

@DzmitryShylovich

This comment has been minimized.

Contributor

DzmitryShylovich commented Dec 4, 2016

Yeah, cannot reproduce using plunkr from #12634 (comment)

@pkozlowski-opensource

This comment has been minimized.

Member

pkozlowski-opensource commented Dec 4, 2016

Thnx @JohannesRudolph and @DzmitryShylovich for confirming. Closing as fixed.

@dgroh

This comment has been minimized.

dgroh commented Aug 2, 2017

I'm facing the same problem.

I cannot navigate within ngOnInit of app.component.ts

The app still works, but I get the error thrown!

That is my code inside ngOnInit:

    let routerInitializerSubscriber = this.router.events.filter(event => event instanceof RoutesRecognized)
    .subscribe((route: RoutesRecognized) => {
      let contractId = route.state.root.firstChild ? Number(route.state.root.firstChild.paramMap.get(ROUTE_PARAM_KEYS.contractId)) : null;

      this.contractService.getContracts()
      .finally(() => routerInitializerSubscriber.unsubscribe())
      .subscribe((contracts) => {
        let contract = contracts.find(v => v.id === contractId);

        this.contracts = contracts;
        this.selectedContract = contract === undefined ? contracts[0] : contract;

        this.router.navigate([`${this.selectedContract.id}/${this.locationService.getPath()}`], { queryParams: this.activatedRoute.snapshot.queryParams });
      });
    });

if I comment out my http request for this.contractService.getContracts() and return mocking data instead , it works. the http request does not throw any exception.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment